From c5b7b002ceb85b3805071cab484cfbeead7194fb Mon Sep 17 00:00:00 2001 From: smolcoder Date: Mon, 8 Dec 2014 20:19:15 +0300 Subject: [PATCH 1/5] Add "isAutoimported" parameter to bifs. --- .../erlang/bif/ErlangBifDescriptor.java | 15 + .../intellij/erlang/bif/ErlangBifParser.java | 16 +- .../intellij/erlang/bif/ErlangBifTable.java | 283 ++++++++++-------- .../erlang/bif/bif.autoimport.tab.txt | 148 +++++++++ 4 files changed, 331 insertions(+), 131 deletions(-) create mode 100644 src/org/intellij/erlang/bif/bif.autoimport.tab.txt diff --git a/src/org/intellij/erlang/bif/ErlangBifDescriptor.java b/src/org/intellij/erlang/bif/ErlangBifDescriptor.java index 42033cf27..39909404d 100644 --- a/src/org/intellij/erlang/bif/ErlangBifDescriptor.java +++ b/src/org/intellij/erlang/bif/ErlangBifDescriptor.java @@ -24,11 +24,23 @@ public final class ErlangBifDescriptor implements Comparable.*\\((.*)\\) ->.*", Pattern.MULTILINE); private static final String BIF_TABLE_PATH = "src/org/intellij/erlang/bif/bif.tab.txt"; + private static final String BIF_AUTOIMPORT_TABLE_PATH = "src/org/intellij/erlang/bif/bif.autoimport.tab.txt"; private static final String GENERATED_FILE = "src/org/intellij/erlang/bif/ErlangBifTable.java"; private static final String ERLANG_SDK_PATH = "/usr/lib/erlang"; private static final String ERLANG_DOC_PATH = "/home/ignatov/Downloads/otp_doc_html_R16B"; @@ -52,11 +57,19 @@ public class ErlangBifParser extends ErlangLightPlatformCodeInsightFixtureTestCa private ErlangDocumentationProvider myDocProvider; + private Set getAutoimportedFunctions() throws IOException { + File bifAutoimportTableFile = new File(BIF_AUTOIMPORT_TABLE_PATH); + String[] bifAutoimportTableText = StringUtil.splitByLines(FileUtilRt.loadFile(bifAutoimportTableFile)); + return new HashSet(ContainerUtil.set(bifAutoimportTableText)); + } + public void testSomething() throws Exception { File bifTableFile = new File(BIF_TABLE_PATH); String[] bifTableText = StringUtil.splitByLines(FileUtilRt.loadFile(bifTableFile)); + PrintStream bifTableJavaBuilder = new PrintStream(new File(GENERATED_FILE)); try { + Set autoimported = getAutoimportedFunctions(); bifTableJavaBuilder.append("package org.intellij.erlang.bif;\n" + "\n" + "import org.jetbrains.annotations.NotNull;\n" + @@ -83,10 +96,11 @@ public void testSomething() throws Exception { String module = matcher.group(1); String name = matcher.group(2); String arity = matcher.group(3); + String isAuroimport = autoimported.contains(name + "/" + arity) ? ", true" : ""; bifTableJavaBuilder.append(" bifMap.putValue(\"").append(module) .append("\", new ErlangBifDescriptor(\"") .append(module).append("\", \"").append(name).append("\", ").append(arity) - .append(", \"").append(fetchSpec(module, name, Integer.valueOf(arity))).append("\"));\n"); + .append(", \"").append(fetchSpec(module, name, Integer.valueOf(arity))).append("\"").append(isAuroimport).append("));\n"); } else if ((matcher = BIF_SEPARATOR.matcher(s)).find()) { String version = matcher.group(1).replaceAll("\\.", ""); diff --git a/src/org/intellij/erlang/bif/ErlangBifTable.java b/src/org/intellij/erlang/bif/ErlangBifTable.java index b577b34bf..20b371f86 100644 --- a/src/org/intellij/erlang/bif/ErlangBifTable.java +++ b/src/org/intellij/erlang/bif/ErlangBifTable.java @@ -16,8 +16,11 @@ package org.intellij.erlang.bif; +import com.intellij.openapi.util.Condition; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -33,119 +36,119 @@ protected Collection createCollection() { }; static { - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "abs", 1, "Int")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "abs", 1, "Int", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "adler32", 1, "Data")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "adler32", 2, "OldAdler, Data")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "adler32_combine", 3, "FirstAdler, SecondAdler, SecondSize")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "apply", 3, "Module, Function, Args")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "atom_to_list", 1, "Atom")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_list", 1, "Binary")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_list", 3, "Binary, Start, Stop")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_term", 1, "Binary")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "check_process_code", 2, "Pid, Module")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "apply", 3, "Module, Function, Args", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "atom_to_list", 1, "Atom", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_list", 1, "Binary", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_list", 3, "Binary, Start, Stop", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_term", 1, "Binary", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "check_process_code", 2, "Pid, Module", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "crc32", 1, "Data")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "crc32", 2, "OldCrc, Data")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "crc32_combine", 3, "FirstCrc, SecondCrc, SecondSize")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "date", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "delete_module", 1, "Module")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "date", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "delete_module", 1, "Module", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "display", 1, "Term")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "display_string", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "display_nl", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "element", 2, "N, Tuple")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "erase", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "erase", 1, "Key")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "exit", 1, "Reason")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "exit", 2, "Pid, Reason")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "element", 2, "N, Tuple", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "erase", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "erase", 1, "Key", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "exit", 1, "Reason", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "exit", 2, "Pid, Reason", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "external_size", 1, "Term")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "external_size", 2, "Term, Options")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float", 1, "Number")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_list", 1, "Float")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_list", 2, "Float, Options")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float", 1, "Number", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_list", 1, "Float", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_list", 2, "Float, Options", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "fun_info", 2, "Fun, Item")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "garbage_collect", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "garbage_collect", 1, "Pid")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get", 1, "Key")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get_keys", 1, "Val")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "group_leader", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "group_leader", 2, "GroupLeader, Pid")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "halt", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "halt", 1, "Status")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "halt", 2, "Status, Options")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "garbage_collect", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "garbage_collect", 1, "Pid", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get", 1, "Key", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get_keys", 1, "Val", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "group_leader", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "group_leader", 2, "GroupLeader, Pid", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "halt", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "halt", 1, "Status", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "halt", 2, "Status, Options", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "phash", 2, "Term, Range")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "phash2", 1, "Term, Range")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "phash2", 2, "Term, Range")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "hd", 1, "List")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "integer_to_list", 1, "Integer")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_alive", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "length", 1, "List")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "link", 1, "PidOrPort")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_atom", 1, "String")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_binary", 1, "IoList")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_float", 1, "String")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_integer", 1, "String")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_pid", 1, "String")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_tuple", 1, "List")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "hd", 1, "List", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "integer_to_list", 1, "Integer", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_alive", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "length", 1, "List", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "link", 1, "PidOrPort", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_atom", 1, "String", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_binary", 1, "IoList", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_float", 1, "String", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_integer", 1, "String", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_pid", 1, "String", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_tuple", 1, "List", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "loaded", 0, "")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "localtime", 0, "")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "localtime_to_universaltime", 2, "Localtime, IsDst")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "make_ref", 0, "")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "make_ref", 0, "", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "md5", 1, "Data")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "md5_init", 0, "")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "md5_update", 2, "Context, Data")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "md5_final", 1, "Context")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "module_loaded", 1, "Module")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "module_loaded", 1, "Module", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "function_exported", 3, "Module, Function, Arity")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "monitor_node", 2, "Node, Flag")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "monitor_node", 2, "Node, Flag", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "monitor_node", 3, "Node, Flag, Options")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "node", 1, "Arg")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "node", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "nodes", 1, "Arg")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "now", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "open_port", 2, "PortName, PortSettings")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "pid_to_list", 1, "Pid")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "node", 1, "Arg", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "node", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "nodes", 1, "Arg", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "now", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "open_port", 2, "PortName, PortSettings", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "pid_to_list", 1, "Pid", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "ports", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "pre_loaded", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_flag", 2, "Flag :: trap_exit, Boolean")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_flag", 3, "Pid, Flag, Value")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_info", 1, "Pid")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_info", 2, "Pid, ItemList")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "processes", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "purge_module", 1, "Module")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "put", 2, "Key, Val")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "register", 2, "RegName, PidOrPort")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "registered", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "round", 1, "Number")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "self", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "setelement", 3, "Index, Tuple1, Value")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "size", 1, "Item")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "spawn", 3, "Module, Function, Args")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "spawn_link", 3, "Module, Function, Args")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "split_binary", 2, "Bin, Pos")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "statistics", 1, "Item :: context_switches")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "term_to_binary", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "term_to_binary", 2, "Term, Options")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "throw", 1, "Any")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "time", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "tl", 1, "List")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "trunc", 1, "Number")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "tuple_to_list", 1, "Tuple")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "pre_loaded", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_flag", 2, "Flag :: trap_exit, Boolean", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_flag", 3, "Pid, Flag, Value", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_info", 1, "Pid", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "process_info", 2, "Pid, ItemList", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "processes", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "purge_module", 1, "Module", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "put", 2, "Key, Val", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "register", 2, "RegName, PidOrPort", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "registered", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "round", 1, "Number", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "self", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "setelement", 3, "Index, Tuple1, Value", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "size", 1, "Item", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "spawn", 3, "Module, Function, Args", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "spawn_link", 3, "Module, Function, Args", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "split_binary", 2, "Bin, Pos", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "statistics", 1, "Item :: context_switches", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "term_to_binary", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "term_to_binary", 2, "Term, Options", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "throw", 1, "Any", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "time", 0, "", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "tl", 1, "List", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "trunc", 1, "Number", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "tuple_to_list", 1, "Tuple", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "universaltime", 0, "")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "universaltime_to_localtime", 1, "Universaltime")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "unlink", 1, "Id")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "unregister", 1, "RegName")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "whereis", 1, "RegName")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "unlink", 1, "Id", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "unregister", 1, "RegName", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "whereis", 1, "RegName", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "spawn_opt", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "setnode", 2, "P1, P2")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "setnode", 3, "P1, P2, P3")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "dist_exit", 3, "P1, P2, P3")); bifMap.putValue("erts_internal", new ErlangBifDescriptor("erts_internal", "port_info", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_call", 3, "Port, Operation, Data")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_command", 2, "Port, Data")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_command", 3, "Port, Data, OptionList")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_control", 3, "Port, Operation, Data")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_close", 1, "Port")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_connect", 2, "Port, Pid")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_command", 2, "Port, Data", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_command", 3, "Port, Data, OptionList", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_control", 3, "Port, Operation, Data", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_close", 1, "Port", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_connect", 2, "Port, Pid", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_set_data", 2, "P1, P2")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_get_data", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "trace_pattern", 2, "MFA, MatchSpec")); @@ -198,12 +201,12 @@ protected Collection createCollection() { bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "ref_to_list", 1, "Ref")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "port_to_list", 1, "Port")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "fun_to_list", 1, "Fun")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "monitor", 2, "Type, Item")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "demonitor", 1, "MonitorRef")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "demonitor", 2, "MonitorRef, OptionList")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_process_alive", 1, "Pid")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "error", 1, "Reason")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "error", 2, "Reason, Args")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "monitor", 2, "Type, Item", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "demonitor", 1, "MonitorRef", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "demonitor", 2, "MonitorRef, OptionList", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_process_alive", 1, "Pid", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "error", 1, "Reason", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "error", 2, "Reason, Args", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "raise", 3, "Class, Reason, Stacktrace")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get_stacktrace", 0, "")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_builtin", 3, "Module, Function, Arity")); @@ -211,20 +214,20 @@ protected Collection createCollection() { bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "send", 3, "Dest, Msg, Options")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "append", 2, "P1, P2")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "subtract", 2, "P1, P2")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_atom", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_list", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_tuple", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_float", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_integer", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_number", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_pid", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_port", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_reference", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_binary", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_function", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_function", 2, "Term, Arity")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_record", 2, "Term, RecordTag")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_record", 3, "Term, RecordTag, Size")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_atom", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_list", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_tuple", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_float", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_integer", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_number", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_pid", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_port", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_reference", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_binary", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_function", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_function", 2, "Term, Arity", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_record", 2, "Term, RecordTag", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_record", 3, "Term, RecordTag, Size", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "match_spec_test", 3, "P1, P2, P3")); bifMap.putValue("ets", new ErlangBifDescriptor("ets", "all", 0, "")); bifMap.putValue("ets", new ErlangBifDescriptor("ets", "new", 2, "Name, Options")); @@ -274,8 +277,8 @@ protected Collection createCollection() { bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "loaded_drivers", 0, "")); bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "info", 2, "Name, Tag")); bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "format_error_int", 1, "P1")); - bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "monitor", 2, "Tag, Item")); - bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "demonitor", 1, "MonitorRef")); + bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "monitor", 2, "Tag, Item", true)); + bifMap.putValue("erl_ddll", new ErlangBifDescriptor("erl_ddll", "demonitor", 1, "MonitorRef", true)); bifMap.putValue("re", new ErlangBifDescriptor("re", "compile", 1, "Regexp")); bifMap.putValue("re", new ErlangBifDescriptor("re", "compile", 2, "Regexp, Options")); bifMap.putValue("re", new ErlangBifDescriptor("re", "run", 2, "Subject, RE")); @@ -303,25 +306,25 @@ protected Collection createCollection() { bifMap.putValue("code", new ErlangBifDescriptor("code", "make_stub_module", 3, "P1, P2, P3")); bifMap.putValue("code", new ErlangBifDescriptor("code", "is_module_native", 1, "Module")); // Since R9C - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "hibernate", 3, "P1, P2, P3")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "hibernate", 3, "Module, Function, Args")); bifMap.putValue("error_logger", new ErlangBifDescriptor("error_logger", "warning_map", 0, "")); // Since R10B bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get_module_info", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "get_module_info", 2, "P1, P2")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_boolean", 1, "Term")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_boolean", 1, "Term", true)); bifMap.putValue("string", new ErlangBifDescriptor("string", "to_integer", 1, "String")); bifMap.putValue("string", new ErlangBifDescriptor("string", "to_float", 1, "String")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "make_fun", 3, "P1, P2, P3")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "iolist_size", 1, "Item")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "iolist_to_binary", 1, "IoListOrBinary")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_existing_atom", 1, "String")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "iolist_size", 1, "Item", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "iolist_to_binary", 1, "IoListOrBinary", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_existing_atom", 1, "String", true)); // Since R12B-0 - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_bitstring", 1, "Term")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "tuple_size", 1, "Tuple")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "byte_size", 1, "Bitstring")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "bit_size", 1, "Bitstring")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_bitstring", 1, "BitstringList")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "bitstring_to_list", 1, "Bitstring")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "is_bitstring", 1, "Term", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "tuple_size", 1, "Tuple", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "byte_size", 1, "Bitstring", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "bit_size", 1, "Bitstring", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_bitstring", 1, "BitstringList", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "bitstring_to_list", 1, "Bitstring", true)); // Since R12B-2 bifMap.putValue("ets", new ErlangBifDescriptor("ets", "update_element", 3, "Tab, Key, ElementSpec :: [{Pos, Value}]")); // Since R12B-4 @@ -331,9 +334,9 @@ protected Collection createCollection() { bifMap.putValue("unicode", new ErlangBifDescriptor("unicode", "characters_to_list", 2, "Data, InEncoding")); bifMap.putValue("unicode", new ErlangBifDescriptor("unicode", "bin_is_7bit", 1, "P1")); // Since R13A - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "atom_to_binary", 2, "Atom, Encoding")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_atom", 2, "Binary, Encoding")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_existing_atom", 2, "Binary, Encoding")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "atom_to_binary", 2, "Atom, Encoding", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_atom", 2, "Binary, Encoding", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_existing_atom", 2, "Binary, Encoding", true)); bifMap.putValue("net_kernel", new ErlangBifDescriptor("net_kernel", "dflag_unicode_io", 1, "P1")); // Since R13B-1 bifMap.putValue("ets", new ErlangBifDescriptor("ets", "give_away", 3, "Tab, Pid, GiftData")); @@ -343,9 +346,9 @@ protected Collection createCollection() { bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "call_on_load_function", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "finish_after_on_load", 2, "P1, P2")); // Since R13B4 - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_term", 2, "Binary, Opts")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_part", 2, "Subject, PosLen")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_part", 3, "Subject, Start, Length")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_term", 2, "Binary, Opts", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_part", 2, "Subject, PosLen", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_part", 3, "Subject, Start, Length", true)); bifMap.putValue("binary", new ErlangBifDescriptor("binary", "compile_pattern", 1, "Pattern")); bifMap.putValue("binary", new ErlangBifDescriptor("binary", "match", 2, "Subject, Pattern")); bifMap.putValue("binary", new ErlangBifDescriptor("binary", "match", 3, "Subject, Pattern, Options")); @@ -376,7 +379,7 @@ protected Collection createCollection() { bifMap.putValue("prim_file", new ErlangBifDescriptor("prim_file", "internal_normalize_utf8", 1, "P1")); bifMap.putValue("prim_file", new ErlangBifDescriptor("prim_file", "is_translatable", 1, "P1")); bifMap.putValue("file", new ErlangBifDescriptor("file", "native_name_encoding", 0, "")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "check_old_code", 1, "Module")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "check_old_code", 1, "Module", true)); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "universaltime_to_posixtime", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "posixtime_to_universaltime", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "dt_put_tag", 1, "P1")); @@ -390,13 +393,13 @@ protected Collection createCollection() { bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "finish_loading", 1, "P1")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "insert_element", 3, "Index, Tuple1, Term")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "delete_element", 2, "Index, Tuple1")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_integer", 1, "Binary")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_integer", 2, "Binary, Base")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "integer_to_binary", 1, "Integer")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_integer", 2, "String, Base")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_binary", 1, "Float")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_binary", 2, "Float, Options")); - bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_float", 1, "Binary")); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_integer", 1, "Binary", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_integer", 2, "Binary, Base", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "integer_to_binary", 1, "Integer", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "list_to_integer", 2, "String, Base", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_binary", 1, "Float", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "float_to_binary", 2, "Float, Options", true)); + bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "binary_to_float", 1, "Binary", true)); bifMap.putValue("io", new ErlangBifDescriptor("io", "printable_range", 0, "")); bifMap.putValue("erlang", new ErlangBifDescriptor("erlang", "hash", 2, "Term, Range")); @@ -407,9 +410,9 @@ protected Collection createCollection() { public static final String MODULE_INFO = "module_info"; private static void putGeneratedInfo() { - bifMap.putValue("", new ErlangBifDescriptor("", "record_info", 2, "Key, Record")); - bifMap.putValue("", new ErlangBifDescriptor("", MODULE_INFO, 0, "")); - bifMap.putValue("", new ErlangBifDescriptor("", MODULE_INFO, 1, "Key")); + bifMap.putValue("", new ErlangBifDescriptor("", "record_info", 2, "Key, Record", true)); + bifMap.putValue("", new ErlangBifDescriptor("", MODULE_INFO, 0, "", true)); + bifMap.putValue("", new ErlangBifDescriptor("", MODULE_INFO, 1, "Key", true)); } private static void putLagerFunctionsToBifMap() { @@ -437,6 +440,16 @@ public static Collection getBifs(@NotNull String moduleName return bifMap.get(moduleName); } + @NotNull + public static Collection getAutoimportedBifs(@NotNull String moduleName) { + return ContainerUtil.filter(bifMap.get(moduleName), new Condition() { + @Override + public boolean value(ErlangBifDescriptor erlangBifDescriptor) { + return erlangBifDescriptor.isAutoImported(); + } + }); + } + @NotNull public static List getBifs(@NotNull String moduleName, @NotNull String functionName) { List bifDescriptors = new ArrayList(); @@ -448,6 +461,16 @@ public static List getBifs(@NotNull String moduleName, @Not return bifDescriptors; } + @Nullable + public static ErlangBifDescriptor getBif(@NotNull String moduleName, @NotNull String functionName, int arity) { + for (ErlangBifDescriptor bifDescriptor : getBifs(moduleName, functionName)) { + if (arity == bifDescriptor.getArity()) { + return bifDescriptor; + } + } + return null; + } + public static boolean isBif(@NotNull String moduleName, @NotNull String functionName, int arity) { Collection erlangBifDescriptors = bifMap.get(moduleName); diff --git a/src/org/intellij/erlang/bif/bif.autoimport.tab.txt b/src/org/intellij/erlang/bif/bif.autoimport.tab.txt new file mode 100644 index 000000000..a2c81ce66 --- /dev/null +++ b/src/org/intellij/erlang/bif/bif.autoimport.tab.txt @@ -0,0 +1,148 @@ +abs/1 +apply/2 +apply/3 +atom_to_binary/2 +atom_to_list/1 +binary_part/2 +binary_part/3 +binary_to_atom/2 +binary_to_existing_atom/2 +binary_to_float/1 +binary_to_integer/1 +binary_to_integer/2 +binary_to_list/1 +binary_to_list/3 +bitstring_to_list/1 +binary_to_term/1 +binary_to_term/2 +bit_size/1 +byte_size/1 +check_old_code/1 +check_process_code/2 +check_process_code/3 +date/0 +delete_module/1 +demonitor/1 +demonitor/2 +disconnect_node/1 +element/2 +erase/0 +erase/1 +error/1 +error/2 +exit/1 +exit/2 +float/1 +float_to_binary/1 +float_to_binary/2 +float_to_list/1 +float_to_list/2 +garbage_collect/0 +garbage_collect/1 +garbage_collect/2 +get/0 +get/1 +get_keys/1 +group_leader/0 +group_leader/2 +halt/0 +halt/1 +halt/2 +hd/1 +integer_to_binary/1 +integer_to_binary/2 +integer_to_list/1 +integer_to_list/2 +iolist_to_binary/1 +iolist_size/1 +is_alive/0 +is_atom/1 +is_binary/1 +is_bitstring/1 +is_boolean/1 +is_float/1 +is_function/1 +is_function/2 +is_integer/1 +is_list/1 +is_map/1 +is_number/1 +is_pid/1 +is_port/1 +is_process_alive/1 +is_record/2 +is_record/3 +is_reference/1 +is_tuple/1 +length/1 +link/1 +list_to_atom/1 +list_to_binary/1 +list_to_bitstring/1 +list_to_existing_atom/1 +list_to_float/1 +list_to_integer/1 +list_to_integer/2 +list_to_pid/1 +list_to_tuple/1 +load_module/2 +make_ref/0 +map_size/1 +max/2 +min/2 +module_loaded/1 +monitor/2 +monitor_node/2 +node/0 +node/1 +nodes/0 +nodes/1 +now/0 +open_port/2 +pid_to_list/1 +port_close/1 +port_command/2 +port_command/3 +port_connect/2 +port_control/3 +pre_loaded/0 +process_flag/2 +process_flag/3 +process_info/1 +process_info/2 +processes/0 +purge_module/1 +put/2 +register/2 +registered/0 +round/1 +self/0 +setelement/3 +size/1 +spawn/1 +spawn/2 +spawn/3 +spawn/4 +spawn_link/1 +spawn_link/2 +spawn_link/3 +spawn_link/4 +spawn_monitor/1 +spawn_monitor/3 +spawn_opt/2 +spawn_opt/3 +spawn_opt/4 +spawn_opt/5 +split_binary/2 +statistics/1 +term_to_binary/1 +term_to_binary/2 +throw/1 +time/0 +tl/1 +trunc/1 +tuple_size/1 +tuple_to_list/1 +unlink/1 +unregister/1 +whereis/1 From bbed6a654d773bb944ca80fc7242132616ccac5c Mon Sep 17 00:00:00 2001 From: smolcoder Date: Wed, 17 Dec 2014 15:46:32 +0300 Subject: [PATCH 2/5] "Defining imported function" inspection. --- .../ErlangDefiningImportedFunction.html | 21 ++++ src/META-INF/plugin.xml | 3 + ...angDefiningImportedFunctionInspection.java | 57 +++++++++ .../erlang/psi/impl/ErlangPsiImplUtil.java | 5 + ...ErlangRemoveFunctionFromImportFixBase.java | 112 ++++++++++++++++++ testData/highlighting/DefineImported1.erl | 3 + testData/highlighting/DefineImported2.erl | 4 + testData/quickfixes/import/common-after.erl | 10 ++ testData/quickfixes/import/common.erl | 11 ++ .../import/duplicateImport-after.erl | 7 ++ .../quickfixes/import/duplicateImport.erl | 8 ++ .../import/multipleImportLines-after.erl | 7 ++ .../quickfixes/import/multipleImportLines.erl | 10 ++ testData/quickfixes/import/noImport-after.erl | 3 + testData/quickfixes/import/noImport.erl | 4 + .../quickfixes/import/oneImport-after.erl | 4 + testData/quickfixes/import/oneImport.erl | 4 + tests/org/intellij/erlang/ErlangTestCase.java | 1 + .../highlighting/ErlangHighlightingTest.java | 2 + .../ErlangHighlightingTestBase.java | 3 +- .../quickfixes/ErlangImportFixTest.java | 43 +++++++ 21 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 resources/inspectionDescriptions/ErlangDefiningImportedFunction.html create mode 100644 src/org/intellij/erlang/inspection/ErlangDefiningImportedFunctionInspection.java create mode 100644 src/org/intellij/erlang/quickfixes/ErlangRemoveFunctionFromImportFixBase.java create mode 100644 testData/highlighting/DefineImported1.erl create mode 100644 testData/highlighting/DefineImported2.erl create mode 100644 testData/quickfixes/import/common-after.erl create mode 100644 testData/quickfixes/import/common.erl create mode 100644 testData/quickfixes/import/duplicateImport-after.erl create mode 100644 testData/quickfixes/import/duplicateImport.erl create mode 100644 testData/quickfixes/import/multipleImportLines-after.erl create mode 100644 testData/quickfixes/import/multipleImportLines.erl create mode 100644 testData/quickfixes/import/noImport-after.erl create mode 100644 testData/quickfixes/import/noImport.erl create mode 100644 testData/quickfixes/import/oneImport-after.erl create mode 100644 testData/quickfixes/import/oneImport.erl create mode 100644 tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java diff --git a/resources/inspectionDescriptions/ErlangDefiningImportedFunction.html b/resources/inspectionDescriptions/ErlangDefiningImportedFunction.html new file mode 100644 index 000000000..84fa83cc3 --- /dev/null +++ b/resources/inspectionDescriptions/ErlangDefiningImportedFunction.html @@ -0,0 +1,21 @@ + + + + +Defining already imported function. + + \ No newline at end of file diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml index ad7f77129..b2ce7780e 100755 --- a/src/META-INF/plugin.xml +++ b/src/META-INF/plugin.xml @@ -175,6 +175,9 @@ + importedFunctionNames = ContainerUtil.newHashSet(); + for (ErlangImportFunction f : file.getImportedFunctions()) { + importedFunctionNames.add(ErlangPsiImplUtil.createFunctionPresentation(f)); + } + for (ErlangFunction function : file.getFunctions()) { + String fullName = ErlangPsiImplUtil.createFunctionPresentation(function); + if (importedFunctionNames.contains(fullName)) { + problemsHolder.registerProblem(InspectionManager.getInstance(file.getProject()).createProblemDescriptor( + function.getNameIdentifier(), + function.getFunctionClauseList().get(0).getArgumentDefinitionList().getOriginalElement(), + "Defining imported function '" + fullName + "'", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, true, + new ErlangRemoveFunctionFix(), + new ErlangRemoveFunctionFromImportFixBase.ErlangRemoveFunctionFromAllImportsFix())); + } + } + } + +} diff --git a/src/org/intellij/erlang/psi/impl/ErlangPsiImplUtil.java b/src/org/intellij/erlang/psi/impl/ErlangPsiImplUtil.java index 26d7f2cf5..ae301648d 100644 --- a/src/org/intellij/erlang/psi/impl/ErlangPsiImplUtil.java +++ b/src/org/intellij/erlang/psi/impl/ErlangPsiImplUtil.java @@ -1397,6 +1397,11 @@ public static String createFunctionPresentation(@NotNull ErlangFunction function return function.getName() + "/" + function.getArity(); } + @NotNull + public static String createFunctionPresentation(@NotNull ErlangImportFunction function) { + return getName(function.getQAtom()) + "/" + getArity(function.getInteger()); + } + @NotNull public static String getQualifiedFunctionName(@NotNull ErlangFunction function) { PsiFile file = function.getContainingFile(); diff --git a/src/org/intellij/erlang/quickfixes/ErlangRemoveFunctionFromImportFixBase.java b/src/org/intellij/erlang/quickfixes/ErlangRemoveFunctionFromImportFixBase.java new file mode 100644 index 000000000..716d33792 --- /dev/null +++ b/src/org/intellij/erlang/quickfixes/ErlangRemoveFunctionFromImportFixBase.java @@ -0,0 +1,112 @@ +/* + * Copyright 2012-2014 Sergey Ignatov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.intellij.erlang.quickfixes; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.ContainerUtil; +import org.intellij.erlang.ErlangTypes; +import org.intellij.erlang.psi.*; +import org.intellij.erlang.psi.impl.ErlangPsiImplUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; + +public abstract class ErlangRemoveFunctionFromImportFixBase extends ErlangQuickFixBase { + @NotNull + @Override + public String getFamilyName() { + return "Remove from import"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + String fullName = getSignature(descriptor.getPsiElement()); + if (fullName == null) return; + removeFunctionFromImport(getAttributesForProcessing(descriptor.getPsiElement()), fullName); + } + + @Nullable + protected abstract String getSignature(@NotNull PsiElement function); + + @NotNull + protected abstract Collection getAttributesForProcessing(@NotNull PsiElement descriptorElement); + + private static void removeFunctionFromImport(@NotNull Collection attributes, + @Nullable String name) { + for (ErlangAttribute attribute : attributes) { + ErlangImportDirective importDirective = attribute.getImportDirective(); + ErlangImportFunctions fns = importDirective != null && importDirective.getModuleRef() != null ? importDirective.getImportFunctions() : null; + List functions = fns == null ? ContainerUtil.emptyList() : fns.getImportFunctionList(); + if (name == null || functions.isEmpty()) continue; + + for (int i = 0; i < functions.size(); ++i) { + String presentation = ErlangPsiImplUtil.createFunctionPresentation(functions.get(i)); + if (presentation.equals(name)) { + cutFunction(functions.get(i), i == functions.size() - 1); + } + } + //noinspection unchecked + if (PsiTreeUtil.getChildOfAnyType(fns, ErlangImportFunction.class, PsiComment.class) == null) { + //noinspection ConstantConditions + if (attribute.getNextSibling() instanceof PsiWhiteSpace) { + attribute.getNextSibling().delete(); + } + attribute.delete(); + } + } + } + + private static void cutFunction(@NotNull ErlangImportFunction function, boolean isLast) { + removeComma(function, false); + if (isLast) removeComma(function, true); + function.delete(); + } + + private static void removeComma(@NotNull ErlangImportFunction function, boolean leftward) { + PsiElement sibling = leftward ? function.getPrevSibling() : function.getNextSibling(); + while (sibling != null) { + if (sibling.getNode().getElementType() == ErlangTypes.ERL_COMMA) { + sibling.delete(); + break; + } + if (!(sibling instanceof PsiComment || sibling instanceof PsiWhiteSpace)) break; + sibling = leftward ? sibling.getPrevSibling() : sibling.getNextSibling(); + } + } + + public static class ErlangRemoveFunctionFromAllImportsFix extends ErlangRemoveFunctionFromImportFixBase { + @Nullable + @Override + protected String getSignature(@NotNull PsiElement function) { + ErlangFunction f = PsiTreeUtil.getParentOfType(function, ErlangFunction.class); + return f != null ? ErlangPsiImplUtil.createFunctionPresentation(f) : null; + } + + @NotNull + @Override + protected Collection getAttributesForProcessing(@NotNull PsiElement descriptorElement) { + return ((ErlangFile) descriptorElement.getContainingFile()).getAttributes(); + } + } +} diff --git a/testData/highlighting/DefineImported1.erl b/testData/highlighting/DefineImported1.erl new file mode 100644 index 000000000..5eb463ace --- /dev/null +++ b/testData/highlighting/DefineImported1.erl @@ -0,0 +1,3 @@ +-import(nio, [crc32/0]). +-export([crc32/0]). +crc32() -> ok. \ No newline at end of file diff --git a/testData/highlighting/DefineImported2.erl b/testData/highlighting/DefineImported2.erl new file mode 100644 index 000000000..552544e49 --- /dev/null +++ b/testData/highlighting/DefineImported2.erl @@ -0,0 +1,4 @@ +-import(nio, [crc32/0]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/common-after.erl b/testData/quickfixes/import/common-after.erl new file mode 100644 index 000000000..07e4f5596 --- /dev/null +++ b/testData/quickfixes/import/common-after.erl @@ -0,0 +1,10 @@ +-import(incl, [ +%% comment +crc32/2 +]). +-import(incl, [foo/0, bar/0]). +-import(erlang, [asdfadf/1]). +-import(erlang, [dt_get_tag/0]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/common.erl b/testData/quickfixes/import/common.erl new file mode 100644 index 000000000..50feb76aa --- /dev/null +++ b/testData/quickfixes/import/common.erl @@ -0,0 +1,11 @@ +-import(incl, [ +%% comment +crc32/1 +, crc32/2 +]). +-import(incl, [foo/0, bar/0]). +-import(erlang, [asdfadf/1]). +-import(erlang, [dt_get_tag/0]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/duplicateImport-after.erl b/testData/quickfixes/import/duplicateImport-after.erl new file mode 100644 index 000000000..aa09bd12f --- /dev/null +++ b/testData/quickfixes/import/duplicateImport-after.erl @@ -0,0 +1,7 @@ +-import(incl, [ + +%% comment +crc32/2]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/duplicateImport.erl b/testData/quickfixes/import/duplicateImport.erl new file mode 100644 index 000000000..0fefb48c2 --- /dev/null +++ b/testData/quickfixes/import/duplicateImport.erl @@ -0,0 +1,8 @@ +-import(incl, [crc32/1, + +crc32/1, +%% comment +crc32/2]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/multipleImportLines-after.erl b/testData/quickfixes/import/multipleImportLines-after.erl new file mode 100644 index 000000000..d459f7223 --- /dev/null +++ b/testData/quickfixes/import/multipleImportLines-after.erl @@ -0,0 +1,7 @@ +%% comment +-import(incl, [ +%% comment +]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/multipleImportLines.erl b/testData/quickfixes/import/multipleImportLines.erl new file mode 100644 index 000000000..ae4458b2e --- /dev/null +++ b/testData/quickfixes/import/multipleImportLines.erl @@ -0,0 +1,10 @@ +-import(incl, [crc32/1]). +-import(incl, [crc32/1]). + +%% comment +-import(incl, [crc32/1 +%% comment +]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/noImport-after.erl b/testData/quickfixes/import/noImport-after.erl new file mode 100644 index 000000000..409bb5933 --- /dev/null +++ b/testData/quickfixes/import/noImport-after.erl @@ -0,0 +1,3 @@ +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/noImport.erl b/testData/quickfixes/import/noImport.erl new file mode 100644 index 000000000..3c0e0e944 --- /dev/null +++ b/testData/quickfixes/import/noImport.erl @@ -0,0 +1,4 @@ +-import(incl, [crc32/1]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/oneImport-after.erl b/testData/quickfixes/import/oneImport-after.erl new file mode 100644 index 000000000..3513d9c86 --- /dev/null +++ b/testData/quickfixes/import/oneImport-after.erl @@ -0,0 +1,4 @@ +-import(incl, [crc32/2]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/oneImport.erl b/testData/quickfixes/import/oneImport.erl new file mode 100644 index 000000000..0e7edfbbb --- /dev/null +++ b/testData/quickfixes/import/oneImport.erl @@ -0,0 +1,4 @@ +-import(incl, [crc32/1, crc32/2]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/tests/org/intellij/erlang/ErlangTestCase.java b/tests/org/intellij/erlang/ErlangTestCase.java index e5d850602..848d5d9e4 100644 --- a/tests/org/intellij/erlang/ErlangTestCase.java +++ b/tests/org/intellij/erlang/ErlangTestCase.java @@ -110,6 +110,7 @@ public static TestSuite suite() { suite.addTestSuite(ErlangMethodSeparatorProviderTest.class); suite.addTestSuite(ErlangMacroParameterResolutionTest.class); suite.addTestSuite(ErlangPerformanceTest.class); + suite.addTestSuite(ErlangImportFixTest.class); return suite; } } diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java index 1e6ff7f93..872747fc9 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java @@ -64,6 +64,8 @@ public class ErlangHighlightingTest extends ErlangHighlightingTestBase { public void testInFunClause() { doTest(); } public void testDuplicateExport1() { doTest(); } public void testDuplicateExport2() { doTest(); } + public void testDefineImported1() { doTest(); } + public void testDefineImported2() { doTest(); } public void testErlang17SyntaxError() { enableErlang17SyntaxInspection(); diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java index d45b0e06c..a91765efa 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java @@ -80,7 +80,8 @@ public static void setUpInspections(@NotNull CodeInsightTestFixture fixture) { ErlangDuplicateFunctionInspection.class, ErlangIncorrectModuleNameInspection.class, ErlangIoFormatInspection.class, - ErlangDuplicateFunctionExportInspection.class + ErlangDuplicateFunctionExportInspection.class, + ErlangDefiningImportedFunctionInspection.class ); } diff --git a/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java new file mode 100644 index 000000000..87c087e11 --- /dev/null +++ b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2014 Sergey Ignatov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.intellij.erlang.quickfixes; + +import org.intellij.erlang.inspection.ErlangDefiningImportedFunctionInspection; + +public class ErlangImportFixTest extends ErlangQuickFixTestBase { + @Override + protected void setUp() throws Exception { + super.setUp(); + //noinspection unchecked + myFixture.enableInspections(ErlangDefiningImportedFunctionInspection.class); + } + + @Override + protected String getTestDataPath() { + return "testData/quickfixes/import/"; + } + + private void doTest() { + doTest("Remove from import"); + } + + public void testCommon() { doTest(); } + public void testMultipleImportLines() { doTest(); } + public void testOneImport() { doTest(); } + public void testDuplicateImport() { doTest(); } + public void testNoImport() { doTest(); } +} \ No newline at end of file From b81c64a26768f33d7f236233ed7e0f92207dff4d Mon Sep 17 00:00:00 2001 From: smolcoder Date: Wed, 17 Dec 2014 16:45:30 +0300 Subject: [PATCH 3/5] Ambiguous call of overridden pre R14 auto-imported BIF --- ...ngAmbiguousCallOfAutoimportedFunction.html | 21 ++++ src/META-INF/plugin.xml | 3 + ...sCallOfAutoimportedFunctionInspection.java | 65 ++++++++++ src/org/intellij/erlang/psi/ErlangFile.java | 4 + .../erlang/psi/impl/ErlangElementFactory.java | 8 ++ .../erlang/psi/impl/ErlangFileImpl.java | 119 ++++++++++++++---- .../ErlangSpecifyModulePrefixFix.java | 47 +++++++ .../intellij/erlang/sdk/ErlangSdkRelease.java | 1 + .../highlighting/AmbiguousAutoimportCall1.erl | 4 + .../highlighting/AmbiguousAutoimportCall2.erl | 4 + .../highlighting/AmbiguousAutoimportCall3.erl | 4 + testData/highlighting/NoAutoImport1.erl | 5 + testData/highlighting/NoAutoImport2.erl | 5 + testData/highlighting/NoAutoImport3.erl | 5 + testData/highlighting/NoAutoImport4.erl | 5 + testData/highlighting/NoAutoImport5.erl | 5 + .../quickfixes/ambiguous/common-after.erl | 2 + testData/quickfixes/ambiguous/common.erl | 2 + .../ambiguous/noAmbiguous-after.erl | 2 + testData/quickfixes/ambiguous/noAmbiguous.erl | 2 + .../ambiguous/nonAutoimport-after.erl | 4 + .../quickfixes/ambiguous/nonAutoimport.erl | 4 + tests/org/intellij/erlang/ErlangTestCase.java | 1 + .../highlighting/ErlangHighlightingTest.java | 10 ++ .../ErlangHighlightingTestBase.java | 3 +- .../quickfixes/ErlangAmbiguousCallTest.java | 51 ++++++++ .../quickfixes/ErlangFunctionFixesTest.java | 4 +- 27 files changed, 363 insertions(+), 27 deletions(-) create mode 100644 resources/inspectionDescriptions/ErlangAmbiguousCallOfAutoimportedFunction.html create mode 100644 src/org/intellij/erlang/inspection/ErlangAmbiguousCallOfAutoimportedFunctionInspection.java create mode 100644 src/org/intellij/erlang/quickfixes/ErlangSpecifyModulePrefixFix.java create mode 100644 testData/highlighting/AmbiguousAutoimportCall1.erl create mode 100644 testData/highlighting/AmbiguousAutoimportCall2.erl create mode 100644 testData/highlighting/AmbiguousAutoimportCall3.erl create mode 100644 testData/highlighting/NoAutoImport1.erl create mode 100644 testData/highlighting/NoAutoImport2.erl create mode 100644 testData/highlighting/NoAutoImport3.erl create mode 100644 testData/highlighting/NoAutoImport4.erl create mode 100644 testData/highlighting/NoAutoImport5.erl create mode 100644 testData/quickfixes/ambiguous/common-after.erl create mode 100644 testData/quickfixes/ambiguous/common.erl create mode 100644 testData/quickfixes/ambiguous/noAmbiguous-after.erl create mode 100644 testData/quickfixes/ambiguous/noAmbiguous.erl create mode 100644 testData/quickfixes/ambiguous/nonAutoimport-after.erl create mode 100644 testData/quickfixes/ambiguous/nonAutoimport.erl create mode 100644 tests/org/intellij/erlang/quickfixes/ErlangAmbiguousCallTest.java diff --git a/resources/inspectionDescriptions/ErlangAmbiguousCallOfAutoimportedFunction.html b/resources/inspectionDescriptions/ErlangAmbiguousCallOfAutoimportedFunction.html new file mode 100644 index 000000000..beecf4f3a --- /dev/null +++ b/resources/inspectionDescriptions/ErlangAmbiguousCallOfAutoimportedFunction.html @@ -0,0 +1,21 @@ + + + + +Ambiguous call of overridden pre R14 auto-imported BIF + + \ No newline at end of file diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml index b2ce7780e..fa505929c 100755 --- a/src/META-INF/plugin.xml +++ b/src/META-INF/plugin.xml @@ -178,6 +178,9 @@ + getImportedFunctions(); diff --git a/src/org/intellij/erlang/psi/impl/ErlangElementFactory.java b/src/org/intellij/erlang/psi/impl/ErlangElementFactory.java index 1676d4ce8..d781cb480 100644 --- a/src/org/intellij/erlang/psi/impl/ErlangElementFactory.java +++ b/src/org/intellij/erlang/psi/impl/ErlangElementFactory.java @@ -65,6 +65,14 @@ public static PsiElement createMacrosFromText(@NotNull Project project, @NotNull return fileFromText.getMacroses().get(0).getMacrosName(); } + @NotNull + public static PsiElement createFunctionWithModuleCallExpression(@NotNull Project project, + @NotNull String moduleName, + @NotNull String functionCallExpr) { + ErlangFile fileFromText = createFileFromText(project, "f() -> " + moduleName + ":" + functionCallExpr + "."); + return fileFromText.getFunctions().get(0).getFunctionClauseList().get(0).getClauseBody().getLastChild(); + } + @NotNull public static PsiElement createStringFromText(@NotNull Project project, @NotNull String text) { return createIncludeString(project, text).getString(); diff --git a/src/org/intellij/erlang/psi/impl/ErlangFileImpl.java b/src/org/intellij/erlang/psi/impl/ErlangFileImpl.java index 6575c409a..076a90184 100644 --- a/src/org/intellij/erlang/psi/impl/ErlangFileImpl.java +++ b/src/org/intellij/erlang/psi/impl/ErlangFileImpl.java @@ -22,19 +22,13 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.FileViewProvider; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiNameIdentifierOwner; -import com.intellij.psi.PsiReference; +import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubTree; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.CachedValue; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.*; import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; @@ -241,6 +235,13 @@ public Result compute() { return Result.create(calcExportAll(), ErlangFileImpl.this); } }, false); + private CachedValue myNoAutoImportAll = + CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider() { + @Override + public Result compute() { + return Result.create(calcNoAutoImportAll(), ErlangFileImpl.this); + } + }, false); private CachedValue> myExportedFunctionsSignatures = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider>() { @Override @@ -248,6 +249,13 @@ public Result> compute() { return Result.create(calcExportedSignatures(), ErlangFileImpl.this); } }, false); + private CachedValue> myNoAutoImportFunctionsSignatures = + CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider>() { + @Override + public Result> compute() { + return Result.create(calcNoAutoImportSignatures(), ErlangFileImpl.this); + } + }, false); @NotNull @Override @@ -268,6 +276,12 @@ public boolean isExported(@NotNull String signature) { return myExportedFunctionsSignatures.getValue().contains(signature); } + @Override + public boolean isNoAutoImport(@NotNull String name, int arity) { + if (isNoAutoImportAll()) return true; + return myNoAutoImportFunctionsSignatures.getValue().contains(name + "/" + arity); + } + @NotNull private Set calcExportedSignatures() { Set result = ContainerUtil.newHashSet(); @@ -286,6 +300,59 @@ private Set calcExportedSignatures() { return result; } + @NotNull + private List getCompileDirectiveExpressions() { + List result = ContainerUtil.newArrayList(); + for (ErlangAttribute attribute : getAttributes()) { + ErlangAtomAttribute atomAttribute = attribute.getAtomAttribute(); + if (atomAttribute == null) continue; + if (!"compile".equals(atomAttribute.getQAtom().getText())) continue; + if (atomAttribute.getAttrVal() == null) continue; + result.addAll(atomAttribute.getAttrVal().getExpressionList()); + } + return result; + } + + @NotNull + private Set calcNoAutoImportSignatures() { + Set result = ContainerUtil.newHashSet(); + for (ErlangExpression expression : getCompileDirectiveExpressions()) { + if (expression instanceof ErlangListExpression) { + for (ErlangExpression tuple : ((ErlangListExpression) expression).getExpressionList()) { + if (tuple instanceof ErlangTupleExpression) { + result.addAll(getNoAutoImportFunctionSignaturesFromTuple((ErlangTupleExpression) tuple)); + } + } + } + else if (expression instanceof ErlangTupleExpression) { + result.addAll(getNoAutoImportFunctionSignaturesFromTuple((ErlangTupleExpression) expression)); + } + } + return result; + } + + @NotNull + private static Set getNoAutoImportFunctionSignaturesFromTuple(@Nullable ErlangTupleExpression tupleExpression) { + Set result = ContainerUtil.newHashSet(); + if (tupleExpression == null || tupleExpression.getExpressionList().size() != 2) return result; + ErlangExpression first = tupleExpression.getExpressionList().get(0); + ErlangExpression second = tupleExpression.getExpressionList().get(1); + if (!(first instanceof ErlangMaxExpression) + || !"no_auto_import".equals(first.getText()) + || !(second instanceof ErlangListExpression)) + return result; + for (ErlangExpression fun : ((ErlangListExpression)second).getExpressionList()) { + List name = ContainerUtil.newArrayList(); + for (PsiElement e : PsiTreeUtil.getChildrenOfTypeAsList(fun, PsiElement.class)) { + if (!(e instanceof PsiWhiteSpace) && !(e instanceof PsiComment)) { + name.add(e.getText()); + } + } + result.add(StringUtil.join(name, "")); + } + return result; + } + @Override public boolean isExportedAll() { //TODO do we use stubs? @@ -296,29 +363,31 @@ public boolean isExportedAll() { return myExportAll.getValue(); } - private Boolean calcExportAll() { - for (ErlangAttribute attribute : getAttributes()) { - ErlangAtomAttribute atomAttribute = attribute.getAtomAttribute(); - if (atomAttribute != null) { - if ("compile".equals(atomAttribute.getQAtom().getText())) { - ErlangAttrVal attrVal = atomAttribute.getAttrVal(); - if (attrVal != null) { - List expressionList = attrVal.getExpressionList(); - for (ErlangExpression expression : expressionList) { - if (expression instanceof ErlangListExpression) { - for (ErlangExpression e : ((ErlangListExpression) expression).getExpressionList()) { - if (e instanceof ErlangMaxExpression && e.getText().equals("export_all")) return true; - } - } - else if (expression instanceof ErlangMaxExpression && expression.getText().equals("export_all")) return true; - } - } + private Boolean containsCompileDirectiveWithOption(@NotNull String option) { + for (ErlangExpression expression : getCompileDirectiveExpressions()) { + if (expression instanceof ErlangListExpression) { + for (ErlangExpression e : ((ErlangListExpression) expression).getExpressionList()) { + if (e instanceof ErlangMaxExpression && e.getText().equals(option)) return true; } } + else if (expression instanceof ErlangMaxExpression && expression.getText().equals(option)) return true; } return false; } + @Override + public boolean isNoAutoImportAll() { + return myNoAutoImportAll.getValue(); + } + + private Boolean calcNoAutoImportAll() { + return containsCompileDirectiveWithOption("no_auto_import"); + } + + private Boolean calcExportAll() { + return containsCompileDirectiveWithOption("export_all"); + } + @NotNull @Override public List getRules() { diff --git a/src/org/intellij/erlang/quickfixes/ErlangSpecifyModulePrefixFix.java b/src/org/intellij/erlang/quickfixes/ErlangSpecifyModulePrefixFix.java new file mode 100644 index 000000000..82c5a0038 --- /dev/null +++ b/src/org/intellij/erlang/quickfixes/ErlangSpecifyModulePrefixFix.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2014 Sergey Ignatov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.intellij.erlang.quickfixes; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.util.PsiTreeUtil; +import org.intellij.erlang.psi.ErlangFunctionCallExpression; +import org.intellij.erlang.psi.impl.ErlangElementFactory; +import org.jetbrains.annotations.NotNull; + +public class ErlangSpecifyModulePrefixFix extends ErlangQuickFixBase { + private final String myModuleName; + + public ErlangSpecifyModulePrefixFix(@NotNull String moduleName) { + myModuleName = moduleName; + } + + @NotNull + @Override + public String getFamilyName() { + return "Specify erlang module"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + ErlangFunctionCallExpression callExpr = PsiTreeUtil.getParentOfType( + descriptor.getPsiElement(), ErlangFunctionCallExpression.class); + if (callExpr == null) return; + callExpr.replace(ErlangElementFactory.createFunctionWithModuleCallExpression(project, myModuleName, callExpr.getText())); + } + +} diff --git a/src/org/intellij/erlang/sdk/ErlangSdkRelease.java b/src/org/intellij/erlang/sdk/ErlangSdkRelease.java index 66d56009d..a5c9b4290 100644 --- a/src/org/intellij/erlang/sdk/ErlangSdkRelease.java +++ b/src/org/intellij/erlang/sdk/ErlangSdkRelease.java @@ -24,6 +24,7 @@ import java.util.regex.Pattern; public final class ErlangSdkRelease { + public static final ErlangSdkRelease V_R14A = new ErlangSdkRelease("R14A", "5.8"); public static final ErlangSdkRelease V_R15B02 = new ErlangSdkRelease("R15B02", "5.9.2"); public static final ErlangSdkRelease V_R16A = new ErlangSdkRelease("R16A", "5.10"); public static final ErlangSdkRelease V_R16B = new ErlangSdkRelease("R16B", "5.10.1"); diff --git a/testData/highlighting/AmbiguousAutoimportCall1.erl b/testData/highlighting/AmbiguousAutoimportCall1.erl new file mode 100644 index 000000000..b6633fdb4 --- /dev/null +++ b/testData/highlighting/AmbiguousAutoimportCall1.erl @@ -0,0 +1,4 @@ +-export([foo/0]). + +abs(I) -> I. +foo() -> abs(3). \ No newline at end of file diff --git a/testData/highlighting/AmbiguousAutoimportCall2.erl b/testData/highlighting/AmbiguousAutoimportCall2.erl new file mode 100644 index 000000000..fcf5d14ce --- /dev/null +++ b/testData/highlighting/AmbiguousAutoimportCall2.erl @@ -0,0 +1,4 @@ +-export([foo/0, abs/1]). + +abs(I) -> I. +foo() -> erlang:abs(3). \ No newline at end of file diff --git a/testData/highlighting/AmbiguousAutoimportCall3.erl b/testData/highlighting/AmbiguousAutoimportCall3.erl new file mode 100644 index 000000000..7e0328118 --- /dev/null +++ b/testData/highlighting/AmbiguousAutoimportCall3.erl @@ -0,0 +1,4 @@ +-export([foo/0]). + +dt_get_tag() -> ok. +foo() -> dt_get_tag(). \ No newline at end of file diff --git a/testData/highlighting/NoAutoImport1.erl b/testData/highlighting/NoAutoImport1.erl new file mode 100644 index 000000000..aa6701487 --- /dev/null +++ b/testData/highlighting/NoAutoImport1.erl @@ -0,0 +1,5 @@ +-export([foo/0]). +-compile(no_auto_import). + +abs(I) -> I. +foo() -> abs(3). \ No newline at end of file diff --git a/testData/highlighting/NoAutoImport2.erl b/testData/highlighting/NoAutoImport2.erl new file mode 100644 index 000000000..9117f11eb --- /dev/null +++ b/testData/highlighting/NoAutoImport2.erl @@ -0,0 +1,5 @@ +-export([foo/0]). +-compile([no_auto_import]). + +abs(I) -> I. +foo() -> abs(3). \ No newline at end of file diff --git a/testData/highlighting/NoAutoImport3.erl b/testData/highlighting/NoAutoImport3.erl new file mode 100644 index 000000000..b3dc7c28d --- /dev/null +++ b/testData/highlighting/NoAutoImport3.erl @@ -0,0 +1,5 @@ +-export([foo/0]). +-compile({no_auto_import, [abs / 1]}). + +abs(I) -> I. +foo() -> abs(3). \ No newline at end of file diff --git a/testData/highlighting/NoAutoImport4.erl b/testData/highlighting/NoAutoImport4.erl new file mode 100644 index 000000000..d80ad837b --- /dev/null +++ b/testData/highlighting/NoAutoImport4.erl @@ -0,0 +1,5 @@ +-export([foo/0]). +-compile([{inline,[pi/0]}, {no_auto_import, [abs / 1, foo/2]}]). + +abs(I) -> I. +foo() -> abs(3). \ No newline at end of file diff --git a/testData/highlighting/NoAutoImport5.erl b/testData/highlighting/NoAutoImport5.erl new file mode 100644 index 000000000..bf67f2a58 --- /dev/null +++ b/testData/highlighting/NoAutoImport5.erl @@ -0,0 +1,5 @@ +-export([foo/0]). +-compile([{no_auto_import, [abs / 3]}]). + +abs(I) -> I. +foo() -> abs(3). \ No newline at end of file diff --git a/testData/quickfixes/ambiguous/common-after.erl b/testData/quickfixes/ambiguous/common-after.erl new file mode 100644 index 000000000..b500744cc --- /dev/null +++ b/testData/quickfixes/ambiguous/common-after.erl @@ -0,0 +1,2 @@ +abs(I) -> ok. +foo() -> erlang:abs(3). diff --git a/testData/quickfixes/ambiguous/common.erl b/testData/quickfixes/ambiguous/common.erl new file mode 100644 index 000000000..4fe03b4f9 --- /dev/null +++ b/testData/quickfixes/ambiguous/common.erl @@ -0,0 +1,2 @@ +abs(I) -> ok. +foo() -> abs(3). diff --git a/testData/quickfixes/ambiguous/noAmbiguous-after.erl b/testData/quickfixes/ambiguous/noAmbiguous-after.erl new file mode 100644 index 000000000..9f1752d35 --- /dev/null +++ b/testData/quickfixes/ambiguous/noAmbiguous-after.erl @@ -0,0 +1,2 @@ +abs() -> ok. +foo() -> abs(3). diff --git a/testData/quickfixes/ambiguous/noAmbiguous.erl b/testData/quickfixes/ambiguous/noAmbiguous.erl new file mode 100644 index 000000000..9f1752d35 --- /dev/null +++ b/testData/quickfixes/ambiguous/noAmbiguous.erl @@ -0,0 +1,2 @@ +abs() -> ok. +foo() -> abs(3). diff --git a/testData/quickfixes/ambiguous/nonAutoimport-after.erl b/testData/quickfixes/ambiguous/nonAutoimport-after.erl new file mode 100644 index 000000000..7e0328118 --- /dev/null +++ b/testData/quickfixes/ambiguous/nonAutoimport-after.erl @@ -0,0 +1,4 @@ +-export([foo/0]). + +dt_get_tag() -> ok. +foo() -> dt_get_tag(). \ No newline at end of file diff --git a/testData/quickfixes/ambiguous/nonAutoimport.erl b/testData/quickfixes/ambiguous/nonAutoimport.erl new file mode 100644 index 000000000..7e0328118 --- /dev/null +++ b/testData/quickfixes/ambiguous/nonAutoimport.erl @@ -0,0 +1,4 @@ +-export([foo/0]). + +dt_get_tag() -> ok. +foo() -> dt_get_tag(). \ No newline at end of file diff --git a/tests/org/intellij/erlang/ErlangTestCase.java b/tests/org/intellij/erlang/ErlangTestCase.java index 848d5d9e4..cab705dd2 100644 --- a/tests/org/intellij/erlang/ErlangTestCase.java +++ b/tests/org/intellij/erlang/ErlangTestCase.java @@ -111,6 +111,7 @@ public static TestSuite suite() { suite.addTestSuite(ErlangMacroParameterResolutionTest.class); suite.addTestSuite(ErlangPerformanceTest.class); suite.addTestSuite(ErlangImportFixTest.class); + suite.addTestSuite(ErlangAmbiguousCallTest.class); return suite; } } diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java index 872747fc9..dce487f80 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java @@ -67,6 +67,16 @@ public class ErlangHighlightingTest extends ErlangHighlightingTestBase { public void testDefineImported1() { doTest(); } public void testDefineImported2() { doTest(); } + public void testAmbiguousAutoimportCall1() { doTest(); } + public void testAmbiguousAutoimportCall2() { doTest(); } + public void testAmbiguousAutoimportCall3() { doTest(); } + + public void testNoAutoImport1() { doTest(); } + public void testNoAutoImport2() { doTest(); } + public void testNoAutoImport3() { doTest(); } + public void testNoAutoImport4() { doTest(); } + public void testNoAutoImport5() { doTest(); } + public void testErlang17SyntaxError() { enableErlang17SyntaxInspection(); doTest(); diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java index a91765efa..192f65204 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java @@ -81,7 +81,8 @@ public static void setUpInspections(@NotNull CodeInsightTestFixture fixture) { ErlangIncorrectModuleNameInspection.class, ErlangIoFormatInspection.class, ErlangDuplicateFunctionExportInspection.class, - ErlangDefiningImportedFunctionInspection.class + ErlangDefiningImportedFunctionInspection.class, + ErlangAmbiguousCallOfAutoimportedFunctionInspection.class ); } diff --git a/tests/org/intellij/erlang/quickfixes/ErlangAmbiguousCallTest.java b/tests/org/intellij/erlang/quickfixes/ErlangAmbiguousCallTest.java new file mode 100644 index 000000000..0d39533c0 --- /dev/null +++ b/tests/org/intellij/erlang/quickfixes/ErlangAmbiguousCallTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2014 Sergey Ignatov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.intellij.erlang.quickfixes; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.util.containers.ContainerUtil; +import org.intellij.erlang.inspection.ErlangAmbiguousCallOfAutoimportedFunctionInspection; + +import java.util.List; + +public class ErlangAmbiguousCallTest extends ErlangQuickFixTestBase { + @Override + protected void setUp() throws Exception { + super.setUp(); + //noinspection unchecked + myFixture.enableInspections( + ErlangAmbiguousCallOfAutoimportedFunctionInspection.class + ); + } + + @Override + protected String getTestDataPath() { + return "testData/quickfixes/ambiguous/"; + } + + private void doTestNoIntention(String prefix) { + String testName = getTestName(true); + myFixture.configureByFile(testName + ".erl"); + List availableIntentions = myFixture.filterAvailableIntentions(prefix); + IntentionAction action = ContainerUtil.getFirstItem(availableIntentions); + assertNull(action); + } + + public void testNoAmbiguous() { doTestNoIntention("Specify erlang module"); } + public void testNonAutoimport() { doTestNoIntention("Specify erlang module"); } + public void testCommon() { doTest("Specify erlang module"); } +} diff --git a/tests/org/intellij/erlang/quickfixes/ErlangFunctionFixesTest.java b/tests/org/intellij/erlang/quickfixes/ErlangFunctionFixesTest.java index f4716e929..b48126729 100644 --- a/tests/org/intellij/erlang/quickfixes/ErlangFunctionFixesTest.java +++ b/tests/org/intellij/erlang/quickfixes/ErlangFunctionFixesTest.java @@ -17,6 +17,7 @@ package org.intellij.erlang.quickfixes; import com.intellij.psi.PsiFile; +import org.intellij.erlang.inspection.ErlangAmbiguousCallOfAutoimportedFunctionInspection; import org.intellij.erlang.inspection.ErlangDuplicateFunctionExportInspection; import org.intellij.erlang.inspection.ErlangUnusedFunctionInspection; import org.intellij.erlang.psi.ErlangExport; @@ -31,7 +32,8 @@ protected void setUp() throws Exception { //noinspection unchecked myFixture.enableInspections( ErlangUnusedFunctionInspection.class, - ErlangDuplicateFunctionExportInspection.class + ErlangDuplicateFunctionExportInspection.class, + ErlangAmbiguousCallOfAutoimportedFunctionInspection.class ); } From bd66d6554eef966ed5042677814615db4aaf9681 Mon Sep 17 00:00:00 2001 From: smolcoder Date: Wed, 17 Dec 2014 17:15:08 +0300 Subject: [PATCH 4/5] "Import directive overrides auto-imported BIF" inspection --- ...portDirectiveOverridesAutoimportedBif.html | 21 ++++++++ src/META-INF/plugin.xml | 3 ++ ...iveOverridesAutoimportedBifInspection.java | 53 +++++++++++++++++++ ...ErlangRemoveFunctionFromImportFixBase.java | 15 ++++++ testData/highlighting/ImportAutoimported.erl | 3 ++ .../import/importAutoimported-after.erl | 1 + .../quickfixes/import/importAutoimported.erl | 1 + .../highlighting/ErlangHighlightingTest.java | 15 ++++++ .../ErlangHighlightingTestBase.java | 3 +- .../quickfixes/ErlangImportFixTest.java | 18 ++++++- 10 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 resources/inspectionDescriptions/ErlangImportDirectiveOverridesAutoimportedBif.html create mode 100644 src/org/intellij/erlang/inspection/ErlangImportDirectiveOverridesAutoimportedBifInspection.java create mode 100644 testData/highlighting/ImportAutoimported.erl create mode 100644 testData/quickfixes/import/importAutoimported-after.erl create mode 100644 testData/quickfixes/import/importAutoimported.erl diff --git a/resources/inspectionDescriptions/ErlangImportDirectiveOverridesAutoimportedBif.html b/resources/inspectionDescriptions/ErlangImportDirectiveOverridesAutoimportedBif.html new file mode 100644 index 000000000..d29a283d5 --- /dev/null +++ b/resources/inspectionDescriptions/ErlangImportDirectiveOverridesAutoimportedBif.html @@ -0,0 +1,21 @@ + + + + +Import directive overrides pre R14 auto-imported BIF. + + \ No newline at end of file diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml index fa505929c..1b44f726f 100755 --- a/src/META-INF/plugin.xml +++ b/src/META-INF/plugin.xml @@ -181,6 +181,9 @@ + getAttributesForProcessing(@NotN return ((ErlangFile) descriptorElement.getContainingFile()).getAttributes(); } } + + public static class ErlangRemoveFunctionFromImportFix extends ErlangRemoveFunctionFromImportFixBase { + @Nullable + @Override + protected String getSignature(@NotNull PsiElement function) { + ErlangImportFunction f = PsiTreeUtil.getParentOfType(function, ErlangImportFunction.class, false); + return (f != null) ? ErlangPsiImplUtil.createFunctionPresentation(f) : null; + } + + @NotNull + @Override + protected Collection getAttributesForProcessing(@NotNull PsiElement descriptorElement) { + return ContainerUtil.createMaybeSingletonList(PsiTreeUtil.getParentOfType(descriptorElement, ErlangAttribute.class)); + } + } } diff --git a/testData/highlighting/ImportAutoimported.erl b/testData/highlighting/ImportAutoimported.erl new file mode 100644 index 000000000..15c7b8486 --- /dev/null +++ b/testData/highlighting/ImportAutoimported.erl @@ -0,0 +1,3 @@ +-import(incl, [dt_get_tag/0, crc32/1, abs/1]). +-export([foo/0]). +foo() -> ok. \ No newline at end of file diff --git a/testData/quickfixes/import/importAutoimported-after.erl b/testData/quickfixes/import/importAutoimported-after.erl new file mode 100644 index 000000000..95169ccee --- /dev/null +++ b/testData/quickfixes/import/importAutoimported-after.erl @@ -0,0 +1 @@ +-import(incl, [dt_get_tag/0, crc32/1]). \ No newline at end of file diff --git a/testData/quickfixes/import/importAutoimported.erl b/testData/quickfixes/import/importAutoimported.erl new file mode 100644 index 000000000..03f06da4e --- /dev/null +++ b/testData/quickfixes/import/importAutoimported.erl @@ -0,0 +1 @@ +-import(incl, [dt_get_tag/0, crc32/1, abs / 1]). \ No newline at end of file diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java index dce487f80..9c0d0e653 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java @@ -77,6 +77,21 @@ public class ErlangHighlightingTest extends ErlangHighlightingTestBase { public void testNoAutoImport4() { doTest(); } public void testNoAutoImport5() { doTest(); } + private void doTestWithInclude() { + myFixture.configureByText("incl.erl", + "-module(incl).\n" + + "-export([crc32/1, abs/1, dt_get_tag/0, bar/0, abs/0]).\n" + + "\n" + + "crc32(Data) -> Data.\n" + + "abs(D) -> D.\n" + + "abs() -> zero.\n" + + "dt_get_tag() -> ok.\n" + + "bar() -> ok."); + doTest(); + } + + public void testImportAutoimported() {doTestWithInclude(); } + public void testErlang17SyntaxError() { enableErlang17SyntaxInspection(); doTest(); diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java index 192f65204..4eaf108e8 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java @@ -82,7 +82,8 @@ public static void setUpInspections(@NotNull CodeInsightTestFixture fixture) { ErlangIoFormatInspection.class, ErlangDuplicateFunctionExportInspection.class, ErlangDefiningImportedFunctionInspection.class, - ErlangAmbiguousCallOfAutoimportedFunctionInspection.class + ErlangAmbiguousCallOfAutoimportedFunctionInspection.class, + ErlangImportDirectiveOverridesAutoimportedBifInspection.class ); } diff --git a/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java index 87c087e11..099d56ae4 100644 --- a/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java +++ b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java @@ -17,13 +17,17 @@ package org.intellij.erlang.quickfixes; import org.intellij.erlang.inspection.ErlangDefiningImportedFunctionInspection; +import org.intellij.erlang.inspection.ErlangImportDirectiveOverridesAutoimportedBifInspection; public class ErlangImportFixTest extends ErlangQuickFixTestBase { @Override protected void setUp() throws Exception { super.setUp(); //noinspection unchecked - myFixture.enableInspections(ErlangDefiningImportedFunctionInspection.class); + myFixture.enableInspections( + ErlangDefiningImportedFunctionInspection.class, + ErlangImportDirectiveOverridesAutoimportedBifInspection.class + ); } @Override @@ -40,4 +44,16 @@ private void doTest() { public void testOneImport() { doTest(); } public void testDuplicateImport() { doTest(); } public void testNoImport() { doTest(); } + public void testImportAutoimported() { + myFixture.configureByText("incl.erl", + "-module(incl).\n" + + "-export([crc32/1, abs/1, dt_get_tag/0, bar/0, abs/0]).\n" + + "\n" + + "crc32(Data) -> Data.\n" + + "abs(D) -> D.\n" + + "abs() -> zero.\n" + + "dt_get_tag() -> ok.\n" + + "bar() -> ok."); + doTest(); + } } \ No newline at end of file From faaf930a0f1e19529a8fba5d0012b680ed6d2121 Mon Sep 17 00:00:00 2001 From: smolcoder Date: Wed, 17 Dec 2014 17:41:06 +0300 Subject: [PATCH 5/5] "Already imported" inspection. --- .../ErlangFunctionAlreadyImported.html | 21 ++++++ src/META-INF/plugin.xml | 3 + ...langFunctionAlreadyImportedInspection.java | 69 +++++++++++++++++++ testData/highlighting/AlreadyImported1.erl | 2 + testData/highlighting/AlreadyImported2.erl | 4 ++ .../import/alreadyImported1-after.erl | 2 + .../quickfixes/import/alreadyImported1.erl | 2 + .../import/alreadyImported2-after.erl | 2 + .../quickfixes/import/alreadyImported2.erl | 4 ++ .../import/duplicateImport-after.erl | 2 +- .../quickfixes/import/noImport2-after.erl | 6 ++ testData/quickfixes/import/noImport2.erl | 6 ++ .../highlighting/ErlangHighlightingTest.java | 2 + .../ErlangHighlightingTestBase.java | 3 +- .../quickfixes/ErlangImportFixTest.java | 29 +++++--- 15 files changed, 145 insertions(+), 12 deletions(-) create mode 100644 resources/inspectionDescriptions/ErlangFunctionAlreadyImported.html create mode 100644 src/org/intellij/erlang/inspection/ErlangFunctionAlreadyImportedInspection.java create mode 100644 testData/highlighting/AlreadyImported1.erl create mode 100644 testData/highlighting/AlreadyImported2.erl create mode 100644 testData/quickfixes/import/alreadyImported1-after.erl create mode 100644 testData/quickfixes/import/alreadyImported1.erl create mode 100644 testData/quickfixes/import/alreadyImported2-after.erl create mode 100644 testData/quickfixes/import/alreadyImported2.erl create mode 100644 testData/quickfixes/import/noImport2-after.erl create mode 100644 testData/quickfixes/import/noImport2.erl diff --git a/resources/inspectionDescriptions/ErlangFunctionAlreadyImported.html b/resources/inspectionDescriptions/ErlangFunctionAlreadyImported.html new file mode 100644 index 000000000..9dd1746f4 --- /dev/null +++ b/resources/inspectionDescriptions/ErlangFunctionAlreadyImported.html @@ -0,0 +1,21 @@ + + + + +Function already imported. + + \ No newline at end of file diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml index 1b44f726f..f23333106 100755 --- a/src/META-INF/plugin.xml +++ b/src/META-INF/plugin.xml @@ -184,6 +184,9 @@ + alreadyImported = ContainerUtil.newHashMap(); + for (ErlangAttribute attribute : file.getAttributes()) { + ErlangImportFunctions importFunctions = + attribute.getImportDirective() != null ? attribute.getImportDirective().getImportFunctions() : null; + if (importFunctions == null) continue; + ErlangModuleRef moduleRef = attribute.getImportDirective().getModuleRef(); + if (moduleRef == null) continue; + processImportDirective(importFunctions, ErlangPsiImplUtil.getName(moduleRef.getQAtom()), + alreadyImported, problemsHolder); + } + } + + private static void processImportDirective(@NotNull ErlangImportFunctions importFunctions, @NotNull String importFrom, + @NotNull Map alreadyImported, + @NotNull ProblemsHolder problemsHolder) { + Set justImported = ContainerUtil.newHashSet(); + for (ErlangImportFunction f : importFunctions.getImportFunctionList()) { + String functionPresentation = ErlangPsiImplUtil.createFunctionPresentation(f); + if (alreadyImported.containsKey(functionPresentation)) { + problemsHolder.registerProblem(f, "Function '" + functionPresentation + "' already imported from '" + + alreadyImported.get(functionPresentation) + "'", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + new ErlangRemoveFunctionFromImportFixBase.ErlangRemoveFunctionFromImportFix()); + } + if (justImported.contains(functionPresentation)) { + problemsHolder.registerProblem(f, "Duplicate import of function '" + functionPresentation + "'", + ProblemHighlightType.WEAK_WARNING, + new ErlangRemoveFunctionFromImportFixBase.ErlangRemoveFunctionFromImportFix()); + } + justImported.add(functionPresentation); + } + for (String name : justImported) { + alreadyImported.put(name, importFrom); + } + } + +} \ No newline at end of file diff --git a/testData/highlighting/AlreadyImported1.erl b/testData/highlighting/AlreadyImported1.erl new file mode 100644 index 000000000..0faf1c575 --- /dev/null +++ b/testData/highlighting/AlreadyImported1.erl @@ -0,0 +1,2 @@ +-import(incl, [crc32/1, crc32/2]). +-import(incl, [crc32/1, crc32/2]). \ No newline at end of file diff --git a/testData/highlighting/AlreadyImported2.erl b/testData/highlighting/AlreadyImported2.erl new file mode 100644 index 000000000..d47b0ef01 --- /dev/null +++ b/testData/highlighting/AlreadyImported2.erl @@ -0,0 +1,4 @@ +-import(incl, [crc32/1, crc32/2, crc32/2]). +-import(incl, [crc32/1, foo/0]). +-import(incl, [foo/0, bar/0]). +-import(incl, [foo/0, dt_get_tag/0]). \ No newline at end of file diff --git a/testData/quickfixes/import/alreadyImported1-after.erl b/testData/quickfixes/import/alreadyImported1-after.erl new file mode 100644 index 000000000..32994a7da --- /dev/null +++ b/testData/quickfixes/import/alreadyImported1-after.erl @@ -0,0 +1,2 @@ +-import(incl, [crc32/1, crc32/2]). +-import(incl, [crc32/2]). \ No newline at end of file diff --git a/testData/quickfixes/import/alreadyImported1.erl b/testData/quickfixes/import/alreadyImported1.erl new file mode 100644 index 000000000..a907c93ed --- /dev/null +++ b/testData/quickfixes/import/alreadyImported1.erl @@ -0,0 +1,2 @@ +-import(incl, [crc32/1, crc32/2]). +-import(incl, [crc32/1, crc32/2]). \ No newline at end of file diff --git a/testData/quickfixes/import/alreadyImported2-after.erl b/testData/quickfixes/import/alreadyImported2-after.erl new file mode 100644 index 000000000..6b208f1a3 --- /dev/null +++ b/testData/quickfixes/import/alreadyImported2-after.erl @@ -0,0 +1,2 @@ +-import(incl, [crc32/1, crc32/2]). +-import(incl, [foo/0, bar/0]). diff --git a/testData/quickfixes/import/alreadyImported2.erl b/testData/quickfixes/import/alreadyImported2.erl new file mode 100644 index 000000000..894c6e2b7 --- /dev/null +++ b/testData/quickfixes/import/alreadyImported2.erl @@ -0,0 +1,4 @@ +-import(incl, [crc32/1, crc32/2]). +-import(incl, [foo/0, bar/0]). +-import(incl, [crc32/1]). + diff --git a/testData/quickfixes/import/duplicateImport-after.erl b/testData/quickfixes/import/duplicateImport-after.erl index aa09bd12f..b6a064733 100644 --- a/testData/quickfixes/import/duplicateImport-after.erl +++ b/testData/quickfixes/import/duplicateImport-after.erl @@ -4,4 +4,4 @@ crc32/2]). -export([crc32/1]). -crc32(Data) -> Data. \ No newline at end of file +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/noImport2-after.erl b/testData/quickfixes/import/noImport2-after.erl new file mode 100644 index 000000000..49835ad2d --- /dev/null +++ b/testData/quickfixes/import/noImport2-after.erl @@ -0,0 +1,6 @@ +-import(incl, [ +%% comment +]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/testData/quickfixes/import/noImport2.erl b/testData/quickfixes/import/noImport2.erl new file mode 100644 index 000000000..68c40f2fd --- /dev/null +++ b/testData/quickfixes/import/noImport2.erl @@ -0,0 +1,6 @@ +-import(incl, [crc32/1 +%% comment +]). +-export([crc32/1]). + +crc32(Data) -> Data. \ No newline at end of file diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java index 9c0d0e653..924d20186 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java @@ -91,6 +91,8 @@ private void doTestWithInclude() { } public void testImportAutoimported() {doTestWithInclude(); } + public void testAlreadyImported1() {doTestWithInclude(); } + public void testAlreadyImported2() {doTestWithInclude(); } public void testErlang17SyntaxError() { enableErlang17SyntaxInspection(); diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java index 4eaf108e8..0d7b87dd9 100644 --- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java +++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java @@ -83,7 +83,8 @@ public static void setUpInspections(@NotNull CodeInsightTestFixture fixture) { ErlangDuplicateFunctionExportInspection.class, ErlangDefiningImportedFunctionInspection.class, ErlangAmbiguousCallOfAutoimportedFunctionInspection.class, - ErlangImportDirectiveOverridesAutoimportedBifInspection.class + ErlangImportDirectiveOverridesAutoimportedBifInspection.class, + ErlangFunctionAlreadyImportedInspection.class ); } diff --git a/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java index 099d56ae4..1721574e1 100644 --- a/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java +++ b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java @@ -17,6 +17,7 @@ package org.intellij.erlang.quickfixes; import org.intellij.erlang.inspection.ErlangDefiningImportedFunctionInspection; +import org.intellij.erlang.inspection.ErlangFunctionAlreadyImportedInspection; import org.intellij.erlang.inspection.ErlangImportDirectiveOverridesAutoimportedBifInspection; public class ErlangImportFixTest extends ErlangQuickFixTestBase { @@ -26,7 +27,8 @@ protected void setUp() throws Exception { //noinspection unchecked myFixture.enableInspections( ErlangDefiningImportedFunctionInspection.class, - ErlangImportDirectiveOverridesAutoimportedBifInspection.class + ErlangImportDirectiveOverridesAutoimportedBifInspection.class, + ErlangFunctionAlreadyImportedInspection.class ); } @@ -36,24 +38,31 @@ protected String getTestDataPath() { } private void doTest() { + loadModule(); doTest("Remove from import"); } - public void testCommon() { doTest(); } - public void testMultipleImportLines() { doTest(); } - public void testOneImport() { doTest(); } - public void testDuplicateImport() { doTest(); } - public void testNoImport() { doTest(); } - public void testImportAutoimported() { + private void loadModule() { myFixture.configureByText("incl.erl", "-module(incl).\n" + - "-export([crc32/1, abs/1, dt_get_tag/0, bar/0, abs/0]).\n" + - "\n" + + "-export([crc32/1, crc32/2, abs/1, dt_get_tag/0, bar/0, abs/0, foo/0]).\n" + + "foo() -> ok.\n" + "crc32(Data) -> Data.\n" + + "crc32(D, T) -> ok.\n" + "abs(D) -> D.\n" + "abs() -> zero.\n" + "dt_get_tag() -> ok.\n" + "bar() -> ok."); - doTest(); } + + public void testCommon() { doTest(); } + public void testMultipleImportLines() { doTest(); } + public void testOneImport() { doTest(); } + public void testDuplicateImport() { doTest(); } + public void testNoImport() { doTest(); } + public void testNoImport2() { doTest(); } + public void testImportAutoimported() { doTest(); } + public void testAlreadyImported1() { doTest(); } + public void testAlreadyImported2() { doTest(); } + } \ No newline at end of file