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/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/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 ad7f77129..1b44f726f 100755
--- a/src/META-INF/plugin.xml
+++ b/src/META-INF/plugin.xml
@@ -175,6 +175,15 @@
+
+
+
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/inspection/ErlangImportDirectiveOverridesAutoimportedBifInspection.java b/src/org/intellij/erlang/inspection/ErlangImportDirectiveOverridesAutoimportedBifInspection.java
new file mode 100644
index 000000000..56a863e1a
--- /dev/null
+++ b/src/org/intellij/erlang/inspection/ErlangImportDirectiveOverridesAutoimportedBifInspection.java
@@ -0,0 +1,52 @@
+/*
+ * 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.inspection;
+
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import org.intellij.erlang.bif.ErlangBifDescriptor;
+import org.intellij.erlang.bif.ErlangBifTable;
+import org.intellij.erlang.psi.ErlangFile;
+import org.intellij.erlang.psi.ErlangImportFunction;
+import org.intellij.erlang.psi.impl.ErlangPsiImplUtil;
+import org.intellij.erlang.quickfixes.ErlangRemoveFunctionFromImportFixBase;
+import org.intellij.erlang.sdk.ErlangSdkRelease;
+import org.intellij.erlang.sdk.ErlangSdkType;
+import org.jetbrains.annotations.NotNull;
+
+public class ErlangImportDirectiveOverridesAutoimportedBifInspection extends ErlangInspectionBase {
+ @Override
+ protected boolean canRunOn(@NotNull ErlangFile file) {
+ ErlangSdkRelease release = ErlangSdkType.getRelease(file);
+ return release == null || release.isNewerThan(ErlangSdkRelease.V_R14A);
+ }
+
+ protected void checkFile(@NotNull ErlangFile file, @NotNull ProblemsHolder problemsHolder) {
+ for (ErlangImportFunction importFunction : file.getImportedFunctions()) {
+ ErlangBifDescriptor bifDescriptor = ErlangBifTable.getBif(
+ "erlang",
+ ErlangPsiImplUtil.getName(importFunction.getQAtom()),
+ ErlangPsiImplUtil.getArity(importFunction.getInteger()));
+ if (bifDescriptor == null || !bifDescriptor.isAutoImported()) continue;
+ problemsHolder.registerProblem(importFunction,
+ "Import directive overrides pre R14 auto-imported BIF '" + ErlangPsiImplUtil.createFunctionPresentation(importFunction) + "'",
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ new ErlangRemoveFunctionFromImportFixBase.ErlangRemoveFunctionFromImportFix());
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/intellij/erlang/psi/ErlangFile.java b/src/org/intellij/erlang/psi/ErlangFile.java
index ea890190b..86eb13915 100644
--- a/src/org/intellij/erlang/psi/ErlangFile.java
+++ b/src/org/intellij/erlang/psi/ErlangFile.java
@@ -79,8 +79,12 @@ public interface ErlangFile extends PsiFile {
boolean isExported(@NotNull String signature);
+ boolean isNoAutoImport(@NotNull String name, int arity);
+
boolean isExportedAll();
+ boolean isNoAutoImportAll();
+
@NotNull
ArrayList 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/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..0d832c020
--- /dev/null
+++ b/src/org/intellij/erlang/quickfixes/ErlangRemoveFunctionFromImportFixBase.java
@@ -0,0 +1,127 @@
+/*
+ * 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 extends ErlangAttribute> getAttributesForProcessing(@NotNull PsiElement descriptorElement);
+
+ private static void removeFunctionFromImport(@NotNull Collection extends ErlangAttribute> 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 extends ErlangAttribute> getAttributesForProcessing(@NotNull PsiElement descriptorElement) {
+ 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 extends ErlangAttribute> getAttributesForProcessing(@NotNull PsiElement descriptorElement) {
+ return ContainerUtil.createMaybeSingletonList(PsiTreeUtil.getParentOfType(descriptorElement, ErlangAttribute.class));
+ }
+ }
+}
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/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/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/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/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/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/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..cab705dd2 100644
--- a/tests/org/intellij/erlang/ErlangTestCase.java
+++ b/tests/org/intellij/erlang/ErlangTestCase.java
@@ -110,6 +110,8 @@ public static TestSuite suite() {
suite.addTestSuite(ErlangMethodSeparatorProviderTest.class);
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 1e6ff7f93..80c38d8b1 100644
--- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java
+++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTest.java
@@ -64,6 +64,33 @@ 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 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(); }
+
+ 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();
diff --git a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java
index d45b0e06c..4eaf108e8 100644
--- a/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java
+++ b/tests/org/intellij/erlang/highlighting/ErlangHighlightingTestBase.java
@@ -80,7 +80,10 @@ public static void setUpInspections(@NotNull CodeInsightTestFixture fixture) {
ErlangDuplicateFunctionInspection.class,
ErlangIncorrectModuleNameInspection.class,
ErlangIoFormatInspection.class,
- ErlangDuplicateFunctionExportInspection.class
+ ErlangDuplicateFunctionExportInspection.class,
+ ErlangDefiningImportedFunctionInspection.class,
+ ErlangAmbiguousCallOfAutoimportedFunctionInspection.class,
+ ErlangImportDirectiveOverridesAutoimportedBifInspection.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
);
}
diff --git a/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.java
new file mode 100644
index 000000000..e29d11764
--- /dev/null
+++ b/tests/org/intellij/erlang/quickfixes/ErlangImportFixTest.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 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,
+ ErlangImportDirectiveOverridesAutoimportedBifInspection.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