diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java
index 07e72ee6000..ea3d2d57700 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java
@@ -4,7 +4,6 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
@@ -42,8 +41,14 @@ public class DiagnosticUtils {
return closestPsiElement.getContainingFile();
}
+ @NotNull
public static String atLocation(@NotNull PsiFile file, @NotNull TextRange textRange) {
- Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
+ Document document = file.getViewProvider().getDocument();//PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
+ return atLocation(file, textRange, document);
+ }
+
+ @NotNull
+ public static String atLocation(PsiFile file, TextRange textRange, Document document) {
int offset = textRange.getStartOffset();
VirtualFile virtualFile = file.getVirtualFile();
String pathSuffix = virtualFile == null ? "" : " in " + virtualFile.getPath();
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
index b03aad99a9e..2d239d6dbaf 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
@@ -355,6 +355,7 @@ public class CallResolver {
if (error) {
failedCandidates.add(candidate);
+ checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
continue;
}
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 184822264e8..48949cbb3f0 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -19,6 +19,11 @@
+
+
+
+
diff --git a/idea/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/idea/src/org/jetbrains/jet/checkers/CheckerTestUtil.java
new file mode 100644
index 00000000000..895019da95c
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/checkers/CheckerTestUtil.java
@@ -0,0 +1,302 @@
+package org.jetbrains.jet.checkers;
+
+import com.google.common.collect.*;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.jet.lang.diagnostics.Diagnostic;
+import org.jetbrains.jet.lang.resolve.BindingContext;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author abreslav
+ */
+public class CheckerTestUtil {
+ public static final Comparator DIAGNOSTIC_COMPARATOR = new Comparator() {
+ @Override
+ public int compare(Diagnostic o1, Diagnostic o2) {
+ TextRange range1 = getTextRange(o1);
+ TextRange range2 = getTextRange(o2);
+ int startOffset1 = range1.getStartOffset();
+ int startOffset2 = range2.getStartOffset();
+ if (startOffset1 != startOffset2) {
+ // Start early -- go first
+ return startOffset1 - range2.getStartOffset();
+ }
+ // start at the same offset, the one who end later is the outer, i.e. goes first
+ return range2.getEndOffset() - range1.getEndOffset();
+ }
+ };
+ private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()");
+ private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile("\\w+");
+
+ public interface DiagnosticDiffCallbacks {
+ void missingDiagnostic(String type, int expectedStart, int expectedEnd);
+ void unexpectedDiagnostic(String type, int actualStart, int actualEnd);
+ }
+
+ public static void diagnosticsDiff(List expected, Collection actual, DiagnosticDiffCallbacks callbacks) {
+ Iterator expectedDiagnostics = expected.iterator();
+ List sortedDiagnosticDescriptors = getSortedDiagnosticDescriptors(actual);
+ Iterator actualDiagnostics = sortedDiagnosticDescriptors.iterator();
+
+ DiagnosedRange currentExpected = safeAdvance(expectedDiagnostics);
+ DiagnosticDescriptor currentActual = safeAdvance(actualDiagnostics);
+ while (currentExpected != null || currentActual != null) {
+ if (currentExpected != null) {
+ if (currentActual == null) {
+ missingDiagnostics(callbacks, currentExpected);
+ currentExpected = safeAdvance(expectedDiagnostics);
+ }
+ else {
+ int expectedStart = currentExpected.getStart();
+ int actualStart = currentActual.getStart();
+ int expectedEnd = currentExpected.getEnd();
+ int actualEnd = currentActual.getEnd();
+ if (expectedStart < actualStart) {
+ missingDiagnostics(callbacks, currentExpected);
+ currentExpected = safeAdvance(expectedDiagnostics);
+ }
+ else if (expectedStart > actualStart) {
+ unexpectedDiagnostics(currentActual.getDiagnostics(), callbacks);
+ currentActual = safeAdvance(actualDiagnostics);
+ }
+ else if (expectedEnd > actualEnd) {
+ assert expectedStart == actualStart;
+ missingDiagnostics(callbacks, currentExpected);
+ currentExpected = safeAdvance(expectedDiagnostics);
+ }
+ else if (expectedEnd < actualEnd) {
+ assert expectedStart == actualStart;
+ unexpectedDiagnostics(currentActual.getDiagnostics(), callbacks);
+ currentActual = safeAdvance(actualDiagnostics);
+ }
+ else {
+ assert expectedStart == actualStart && expectedEnd == actualEnd;
+ Multiset actualDiagnosticTypes = currentActual.getDiagnosticTypeStrings();
+ Multiset expectedDiagnosticTypes = currentExpected.getDiagnostics();
+ if (!actualDiagnosticTypes.equals(expectedDiagnosticTypes)) {
+ Multiset expectedCopy = HashMultiset.create(expectedDiagnosticTypes);
+ expectedCopy.removeAll(actualDiagnosticTypes);
+ Multiset actualCopy = HashMultiset.create(actualDiagnosticTypes);
+ actualCopy.removeAll(expectedDiagnosticTypes);
+
+ for (String type : expectedCopy) {
+ callbacks.missingDiagnostic(type, expectedStart, expectedEnd);
+ }
+ for (String type : actualCopy) {
+ callbacks.unexpectedDiagnostic(type, actualStart, actualEnd);
+ }
+ }
+ currentExpected = safeAdvance(expectedDiagnostics);
+ currentActual = safeAdvance(actualDiagnostics);
+ }
+
+ }
+ }
+ else {
+ if (currentActual != null) {
+ unexpectedDiagnostics(currentActual.getDiagnostics(), callbacks);
+ currentActual = safeAdvance(actualDiagnostics);
+ }
+ else {
+ break;
+ }
+ }
+
+// assert expectedDiagnostics.hasNext() || actualDiagnostics.hasNext();
+ }
+ }
+
+ private static void unexpectedDiagnostics(List actual, DiagnosticDiffCallbacks callbacks) {
+ for (Diagnostic diagnostic : actual) {
+ TextRange textRange = getTextRange(diagnostic);
+ callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset());
+ }
+ }
+
+ private static void missingDiagnostics(DiagnosticDiffCallbacks callbacks, DiagnosedRange currentExpected) {
+ for (String type : currentExpected.getDiagnostics()) {
+ callbacks.missingDiagnostic(type, currentExpected.getStart(), currentExpected.getEnd());
+ }
+ }
+
+ private static T safeAdvance(Iterator iterator) {
+ return iterator.hasNext() ? iterator.next() : null;
+ }
+
+ public static String parseDiagnosedRanges(String text, List result) {
+ Matcher matcher = RANGE_START_OR_END_PATTERN.matcher(text);
+
+ Stack opened = new Stack();
+
+ int offsetCompensation = 0;
+
+ while (matcher.find()) {
+ int effectiveOffset = matcher.start() - offsetCompensation;
+ String matchedText = matcher.group();
+ if ("".equals(matchedText)) {
+ opened.pop().setEnd(effectiveOffset);
+ }
+ else {
+ Matcher diagnosticTypeMatcher = INDIVIDUAL_DIAGNOSTIC_PATTERN.matcher(matchedText);
+ DiagnosedRange range = new DiagnosedRange(effectiveOffset);
+ while (diagnosticTypeMatcher.find()) {
+ range.addDiagnostic(diagnosticTypeMatcher.group());
+ }
+ opened.push(range);
+ result.add(range);
+ }
+ offsetCompensation += matchedText.length();
+ }
+
+ matcher.reset();
+ return matcher.replaceAll("");
+ }
+
+ public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext) {
+ Collection diagnostics = bindingContext.getDiagnostics();
+
+ StringBuffer result = new StringBuffer();
+ String text = psiFile.getText();
+ if (!diagnostics.isEmpty()) {
+ List diagnosticDescriptors = getSortedDiagnosticDescriptors(diagnostics);
+
+ Stack opened = new Stack();
+ ListIterator iterator = diagnosticDescriptors.listIterator();
+ DiagnosticDescriptor currentDescriptor = iterator.next();
+
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ while (!opened.isEmpty() && i == opened.peek().end) {
+ closeDiagnosticString(result);
+ opened.pop();
+ }
+ if (currentDescriptor != null && i == currentDescriptor.start) {
+ openDiagnosticsString(result, currentDescriptor);
+ opened.push(currentDescriptor);
+ if (iterator.hasNext()) {
+ currentDescriptor = iterator.next();
+ }
+ else {
+ currentDescriptor = null;
+ }
+ }
+ result.append(c);
+ }
+ }
+ else {
+ result.append(text);
+ }
+ return result;
+ }
+
+ private static void openDiagnosticsString(StringBuffer result, DiagnosticDescriptor currentDescriptor) {
+ result.append(" iterator = currentDescriptor.diagnostics.iterator(); iterator.hasNext(); ) {
+ Diagnostic diagnostic = iterator.next();
+ result.append(diagnostic.getFactory().getName());
+ if (iterator.hasNext()) {
+ result.append(", ");
+ }
+ }
+ result.append("!>");
+ }
+
+ private static void closeDiagnosticString(StringBuffer result) {
+ result.append("");
+ }
+
+ private static List getSortedDiagnosticDescriptors(Collection diagnostics) {
+ List list = Lists.newArrayList(diagnostics);
+ Collections.sort(list, DIAGNOSTIC_COMPARATOR);
+
+ List diagnosticDescriptors = Lists.newArrayList();
+ DiagnosticDescriptor currentDiagnosticDescriptor = null;
+ for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
+ Diagnostic diagnostic = iterator.next();
+
+ TextRange textRange = getTextRange(diagnostic);
+ if (currentDiagnosticDescriptor != null && currentDiagnosticDescriptor.equalRange(textRange)) {
+ currentDiagnosticDescriptor.diagnostics.add(diagnostic);
+ }
+ else {
+ currentDiagnosticDescriptor = new DiagnosticDescriptor(textRange.getStartOffset(), textRange.getEndOffset(), diagnostic);
+ diagnosticDescriptors.add(currentDiagnosticDescriptor);
+ }
+ }
+ return diagnosticDescriptors;
+ }
+
+ private static TextRange getTextRange(Diagnostic currentDiagnostic) {
+ return currentDiagnostic.getFactory().getTextRange(currentDiagnostic);
+ }
+
+ private static class DiagnosticDescriptor {
+ private final int start;
+ private final int end;
+ private final List diagnostics = Lists.newArrayList();
+
+ DiagnosticDescriptor(int start, int end, Diagnostic diagnostic) {
+ this.start = start;
+ this.end = end;
+ this.diagnostics.add(diagnostic);
+ }
+
+ public boolean equalRange(TextRange textRange) {
+ return start == textRange.getStartOffset() && end == textRange.getEndOffset();
+ }
+
+ public Multiset getDiagnosticTypeStrings() {
+ Multiset actualDiagnosticTypes = HashMultiset.create();
+ for (Diagnostic diagnostic : diagnostics) {
+ actualDiagnosticTypes.add(diagnostic.getFactory().getName());
+ }
+ return actualDiagnosticTypes;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public List getDiagnostics() {
+ return diagnostics;
+ }
+ }
+
+ public static class DiagnosedRange {
+ private final int start;
+ private int end;
+ private final Multiset diagnostics = HashMultiset.create();
+
+ private DiagnosedRange(int start) {
+ this.start = start;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public Multiset getDiagnostics() {
+ return diagnostics;
+ }
+
+ public void setEnd(int end) {
+ this.end = end;
+ }
+
+ public void addDiagnostic(String diagnostic) {
+ diagnostics.add(diagnostic);
+ }
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java
new file mode 100644
index 00000000000..b9c35a7986d
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java
@@ -0,0 +1,50 @@
+package org.jetbrains.jet.plugin.actions;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.jet.checkers.CheckerTestUtil;
+import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.jet.plugin.AnalyzerFacade;
+
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+
+/**
+ * @author abreslav
+ */
+public class CopyAsDiagnosticTestAction extends AnAction {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Editor editor = e.getData(PlatformDataKeys.EDITOR);
+ PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
+ assert editor != null && psiFile != null;
+
+ BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) psiFile);
+
+ String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
+
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(new StringSelection(result), new ClipboardOwner() {
+ @Override
+ public void lostOwnership(Clipboard clipboard, Transferable contents) {}
+ });
+ }
+
+
+ @Override
+ public void update(AnActionEvent e) {
+ Editor editor = e.getData(PlatformDataKeys.EDITOR);
+ PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
+ e.getPresentation().setEnabled(editor != null && psiFile instanceof JetFile && ApplicationManager.getApplication().isInternal());
+ }
+
+}
diff --git a/idea/testData/checkerTestUtil/test.jet b/idea/testData/checkerTestUtil/test.jet
new file mode 100644
index 00000000000..e78606b8885
--- /dev/null
+++ b/idea/testData/checkerTestUtil/test.jet
@@ -0,0 +1,15 @@
+fun foo(u : Unit) : Int = 1
+
+fun test() : Int {
+ foo(1)
+ val a : fun() : Unit = {
+ foo(1)
+ }
+ return 1 - "1"
+}
+
+class A() {
+ val x : Int = foo1(xx)
+}
+
+fun foo1() {}
\ No newline at end of file
diff --git a/idea/testData/checkerWithErrorTypes/quick/Abstract.jet b/idea/testData/checkerWithErrorTypes/quick/Abstract.jet
new file mode 100644
index 00000000000..e30dabbd6ab
--- /dev/null
+++ b/idea/testData/checkerWithErrorTypes/quick/Abstract.jet
@@ -0,0 +1,241 @@
+namespace abstract
+
+class MyClass() {
+ //properties
+ val a: Int
+ val a1: Int = 1
+ abstract val a2: Int
+ abstract val a3: Int = 1
+
+ var b: Int private set
+ var b1: Int = 0; private set
+ abstract var b2: Int private set
+ abstract var b3: Int = 0; private set
+
+ var c: Int set(v: Int) { $c = v }
+ var c1: Int = 0; set(v: Int) { $c1 = v }
+ abstract var c2: Int set(v: Int) { $c2 = v }
+ abstract var c3: Int = 0; set(v: Int) { $c3 = v }
+
+ val e: Int get() = a
+ val e1: Int = 0; get() = a
+ abstract val e2: Int get() = a
+ abstract val e3: Int = 0; get() = a
+
+ //methods
+ fun f()
+ fun g() {}
+ abstract fun h()
+ abstract fun j() {}
+
+ //property accessors
+ var i: Int abstract get abstract set
+ var i1: Int = 0; abstract get abstract set
+
+ var j: Int get() = i; abstract set
+ var j1: Int = 0; get() = i; abstract set
+
+ var k: Int abstract set
+ var k1: Int = 0; abstract set
+
+ var l: Int abstract get abstract set
+ var l1: Int = 0; abstract get abstract set
+
+ var n: Int abstract get abstract set(v: Int) {}
+}
+
+abstract class MyAbstractClass() {
+ //properties
+ val a: Int
+ val a1: Int = 1
+ abstract val a2: Int
+ abstract val a3: Int = 1
+
+ var b: Int private set
+ var b1: Int = 0; private set
+ abstract var b2: Int private set
+ abstract var b3: Int = 0; private set
+
+ var c: Int set(v: Int) { $c = v }
+ var c1: Int = 0; set(v: Int) { $c1 = v }
+ abstract var c2: Int set(v: Int) { $c2 = v }
+ abstract var c3: Int = 0; set(v: Int) { $c3 = v }
+
+ val e: Int get() = a
+ val e1: Int = 0; get() = a
+ abstract val e2: Int get() = a
+ abstract val e3: Int = 0; get() = a
+
+ //methods
+ fun f()
+ fun g() {}
+ abstract fun h()
+ abstract fun j() {}
+
+ //property accessors
+ var i: Int abstract get abstract set
+ var i1: Int = 0; abstract get abstract set
+
+ var j: Int get() = i; abstract set
+ var j1: Int get() = i; abstract set
+
+ var k: Int abstract set
+ var k1: Int = 0; abstract set
+
+ var l: Int abstract get abstract set
+ var l1: Int = 0; abstract get abstract set
+
+ var n: Int abstract get abstract set(v: Int) {}
+}
+
+trait MyTrait {
+ //properties
+ val a: Int
+ val a1: Int = 1
+ abstract val a2: Int
+ abstract val a3: Int = 1
+
+ var b: Int private set
+ var b1: Int = 0; private set
+ abstract var b2: Int private set
+ abstract var b3: Int = 0; private set
+
+ var c: Int set(v: Int) { $c = v }
+ var c1: Int = 0; set(v: Int) { $c1 = v }
+ abstract var c2: Int set(v: Int) { $c2 = v }
+ abstract var c3: Int = 0; set(v: Int) { $c3 = v }
+
+ val e: Int get() = a
+ val e1: Int = 0; get() = a
+ abstract val e2: Int get() = a
+ abstract val e3: Int = 0; get() = a
+
+ //methods
+ fun f()
+ fun g() {}
+ abstract fun h()
+ abstract fun j() {}
+
+ //property accessors
+ var i: Int abstract get abstract set
+ var i1: Int = 0; abstract get abstract set
+
+ var j: Int get() = i; abstract set
+ var j1: Int = 0; get() = i; abstract set
+
+ var k: Int abstract set
+ var k1: Int = 0; abstract set
+
+ var l: Int abstract get abstract set
+ var l1: Int = 0; abstract get abstract set
+
+ var n: Int abstract get abstract set(v: Int) {}
+}
+
+enum class MyEnum() {
+ //properties
+ val a: Int
+ val a1: Int = 1
+ abstract val a2: Int
+ abstract val a3: Int = 1
+
+ var b: Int private set
+ var b1: Int = 0; private set
+ abstract var b2: Int private set
+ abstract var b3: Int = 0; private set
+
+ var c: Int set(v: Int) { $c = v }
+ var c1: Int = 0; set(v: Int) { $c1 = v }
+ abstract var c2: Int set(v: Int) { $c2 = v }
+ abstract var c3: Int = 0; set(v: Int) { $c3 = v }
+
+ val e: Int get() = a
+ val e1: Int = 0; get() = a
+ abstract val e2: Int get() = a
+ abstract val e3: Int = 0; get() = a
+
+ //methods
+ fun f()
+ fun g() {}
+ abstract fun h()
+ abstract fun j() {}
+
+ //property accessors
+ var i: Int abstract get abstract set
+ var i1: Int = 0; abstract get abstract set
+
+ var j: Int get() = i; abstract set
+ var j1: Int = 0; get() = i; abstract set
+
+ var k: Int abstract set
+ var k1: Int = 0; abstract set
+
+ var l: Int abstract get abstract set
+ var l1: Int = 0; abstract get abstract set
+
+ var n: Int abstract get abstract set(v: Int) {}
+}
+
+abstract enum class MyAbstractEnum() {}
+
+namespace MyNamespace {
+ //properties
+ val a: Int
+ val a1: Int = 1
+ abstract val a2: Int
+ abstract val a3: Int = 1
+
+ var b: Int private set
+ var b1: Int = 0; private set
+ abstract var b2: Int private set
+ abstract var b3: Int = 0; private set
+
+ var c: Int set(v: Int) { $c = v }
+ var c1: Int = 0; set(v: Int) { $c1 = v }
+ abstract var c2: Int set(v: Int) { $c2 = v }
+ abstract var c3: Int = 0; set(v: Int) { $c3 = v }
+
+ val e: Int get() = a
+ val e1: Int = 0; get() = a
+ abstract val e2: Int get() = a
+ abstract val e3: Int = 0; get() = a
+
+ //methods
+ fun f()
+ fun g() {}
+ abstract fun h()
+ abstract fun j() {}
+
+ //property accessors
+ var i: Int abstract get abstract set
+ var i1: Int = 0; abstract get abstract set
+
+ var j: Int get() = i; abstract set
+ var j1: Int = 0; get() = i; abstract set
+
+ var k: Int abstract set
+ var k1: Int = 0; abstract set
+
+ var l: Int abstract get abstract set
+ var l1: Int = 0; abstract get abstract set
+
+ var n: Int abstract get abstract set(v: Int) {}
+}
+
+//creating an instance
+abstract class B1(
+ val i: Int,
+ val s: String
+) {
+}
+
+class B2() : B1(1, "r") {}
+
+abstract class B3(i: Int) {
+ this(): this(1)
+}
+
+fun foo(a: B3) {
+ val a = B3()
+ val b = B1(2, "s")
+}
\ No newline at end of file
diff --git a/idea/testData/checkerWithErrorTypes/quick/Basic.jet b/idea/testData/checkerWithErrorTypes/quick/Basic.jet
new file mode 100644
index 00000000000..dea3b44a6e1
--- /dev/null
+++ b/idea/testData/checkerWithErrorTypes/quick/Basic.jet
@@ -0,0 +1,15 @@
+fun foo(u : Unit) : Int = 1
+
+fun test() : Int {
+ foo(1)
+ val a : fun() : Unit = {
+ foo(1)
+ }
+ return 1 - "1"
+}
+
+class A() {
+ val x : Int = foo1(xx)
+}
+
+fun foo1() {}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/JetLiteFixture.java b/idea/tests/org/jetbrains/jet/JetLiteFixture.java
new file mode 100644
index 00000000000..d3b1f6b3af3
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/JetLiteFixture.java
@@ -0,0 +1,189 @@
+package org.jetbrains.jet;
+
+import com.intellij.ide.startup.impl.StartupManagerImpl;
+import com.intellij.lang.*;
+import com.intellij.lang.impl.PsiBuilderFactoryImpl;
+import com.intellij.mock.*;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
+import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.fileTypes.FileTypeFactory;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.options.SchemesManagerFactory;
+import com.intellij.openapi.progress.impl.ProgressManagerImpl;
+import com.intellij.openapi.startup.StartupManager;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiCachedValuesFactory;
+import com.intellij.psi.impl.PsiFileFactoryImpl;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
+import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.testFramework.MockSchemesManagerFactory;
+import com.intellij.testFramework.PlatformLiteFixture;
+import com.intellij.testFramework.TestDataFile;
+import com.intellij.util.CachedValuesManagerImpl;
+import com.intellij.util.Function;
+import com.intellij.util.messages.MessageBus;
+import com.intellij.util.messages.MessageBusFactory;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.jet.lang.parsing.JetParserDefinition;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.PicoContainer;
+import org.picocontainer.PicoInitializationException;
+import org.picocontainer.PicoIntrospectionException;
+import org.picocontainer.defaults.AbstractComponentAdapter;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author abreslav
+ */
+public class JetLiteFixture extends PlatformLiteFixture {
+ protected String myFileExt;
+ @NonNls
+ protected final String myFullDataPath;
+ protected PsiFile myFile;
+ private MockPsiManager myPsiManager;
+ private PsiFileFactoryImpl myFileFactory;
+ protected Language myLanguage;
+ protected final ParserDefinition[] myDefinitions;
+
+ public JetLiteFixture(@NonNls String dataPath) {
+ myFileExt = "jet";
+ myFullDataPath = getTestDataPath() + "/" + dataPath;
+ myDefinitions = new ParserDefinition[] {new JetParserDefinition()};
+ }
+
+ protected String getTestDataPath() {
+ return JetTestCaseBase.getTestDataPathBase();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ initApplication();
+ getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter("com.intellij.openapi.progress.ProgressManager", Object.class) {
+ @Override
+ public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException {
+ return new ProgressManagerImpl(getApplication());
+ }
+
+ @Override
+ public void verify(PicoContainer container) throws PicoIntrospectionException {
+ }
+ });
+ myProject = disposeOnTearDown(new MockProjectEx());
+ myPsiManager = new MockPsiManager(myProject);
+ myFileFactory = new PsiFileFactoryImpl(myPsiManager);
+ final MutablePicoContainer appContainer = getApplication().getPicoContainer();
+ registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication()));
+ registerComponentInstance(appContainer, SchemesManagerFactory.class, new MockSchemesManagerFactory());
+ final MockEditorFactory editorFactory = new MockEditorFactory();
+ registerComponentInstance(appContainer, EditorFactory.class, editorFactory);
+ registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function() {
+ @Override
+ public Document fun(CharSequence charSequence) {
+ return editorFactory.createDocument(charSequence);
+ }
+ }, FileDocumentManagerImpl.DOCUMENT_KEY));
+ registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager());
+ myLanguage = myLanguage == null && myDefinitions != null && myDefinitions.length > 0
+ ? myDefinitions[0].getFileNodeType().getLanguage()
+ : myLanguage;
+ registerComponentInstance(appContainer, FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt)));
+ registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl());
+ registerApplicationService(DefaultASTFactory.class, new DefaultASTFactoryImpl());
+ registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl());
+ myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager)));
+ myProject.registerService(PsiManager.class, myPsiManager);
+ myProject.registerService(StartupManager.class, new StartupManagerImpl(myProject));
+ myProject.registerService(PsiFileFactory.class, new PsiFileFactoryImpl(myPsiManager));
+
+ registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class);
+
+ for (ParserDefinition definition : myDefinitions) {
+ addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ myFile = null;
+ myProject = null;
+ myPsiManager = null;
+ }
+
+ protected String loadFile(@NonNls @TestDataFile String name) throws IOException {
+ return doLoadFile(myFullDataPath, name);
+ }
+
+ private static String doLoadFile(String myFullDataPath, String name) throws IOException {
+ String fullName = myFullDataPath + File.separatorChar + name;
+ String text = FileUtil.loadFile(new File(fullName), CharsetToolkit.UTF8).trim();
+ text = StringUtil.convertLineSeparators(text);
+ return text;
+ }
+
+ protected PsiFile createPsiFile(String name, String text) {
+ return createFile(name + "." + myFileExt, text);
+ }
+
+ protected PsiFile createFile(@NonNls String name, String text) {
+ LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text);
+ virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
+ return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false);
+ }
+
+ protected static void ensureParsed(PsiFile file) {
+ file.accept(new PsiElementVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ element.acceptChildren(this);
+ }
+ });
+ }
+
+ protected void registerApplicationService(final Class aClass, T object) {
+ getApplication().registerService(aClass, object);
+ Disposer.register(myProject, new Disposable() {
+ @Override
+ public void dispose() {
+ getApplication().getPicoContainer().unregisterComponent(aClass.getName());
+ }
+ });
+ }
+
+ protected void addExplicitExtension(final LanguageExtension instance, final Language language, final T object) {
+ instance.addExplicitExtension(language, object);
+ Disposer.register(myProject, new Disposable() {
+ @Override
+ public void dispose() {
+ instance.removeExplicitExtension(language, object);
+ }
+ });
+ }
+
+ protected void prepareForTest(String name) throws IOException {
+ String text = loadFile(name + "." + myFileExt);
+ createAndCheckPsiFile(name, text);
+ }
+
+ protected void createAndCheckPsiFile(String name, String text) {
+ myFile = createPsiFile(name, text);
+ ensureParsed(myFile);
+ assertEquals("light virtual file text mismatch", text, ((LightVirtualFile) myFile.getVirtualFile()).getContent().toString());
+ assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile()));
+ assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText());
+ assertEquals("psi text mismatch", text, myFile.getText());
+ }
+}
diff --git a/idea/tests/org/jetbrains/jet/JetTestCaseBase.java b/idea/tests/org/jetbrains/jet/JetTestCaseBase.java
index 5ae4d8ff51e..e13ee48f159 100644
--- a/idea/tests/org/jetbrains/jet/JetTestCaseBase.java
+++ b/idea/tests/org/jetbrains/jet/JetTestCaseBase.java
@@ -43,11 +43,11 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase {
return getTestDataPathBase();
}
- protected static String getTestDataPathBase() {
+ public static String getTestDataPathBase() {
return getHomeDirectory() + "/idea/testData";
}
- private static String getHomeDirectory() {
+ public static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetTestCaseBase.class, "/org/jetbrains/jet/JetTestCaseBase.class")).getParentFile().getParentFile().getParent();
}
diff --git a/idea/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/idea/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java
new file mode 100644
index 00000000000..b2d27a6d52b
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java
@@ -0,0 +1,125 @@
+package org.jetbrains.jet.checkers;
+
+import com.google.common.collect.Lists;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.jet.JetLiteFixture;
+import org.jetbrains.jet.lang.diagnostics.Diagnostic;
+import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
+import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.jet.lang.resolve.ImportingStrategy;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author abreslav
+ */
+public class CheckerTestUtilTest extends JetLiteFixture {
+
+ public CheckerTestUtilTest() {
+ super("checkerTestUtil");
+ }
+
+ protected void doTest(TheTest theTest) throws Exception {
+ prepareForTest("test");
+ theTest.test(myFile);
+ }
+
+ public void testEquals() throws Exception {
+ doTest(new TheTest() {
+ @Override
+ protected void makeTestData(List diagnostics, List diagnosedRanges) {
+ }
+ });
+ }
+
+ public void testMissing() throws Exception {
+ doTest(new TheTest("Missing TYPE_MISMATCH at 56 to 57") {
+ @Override
+ protected void makeTestData(List diagnostics, List diagnosedRanges) {
+ diagnostics.remove(0);
+ }
+ });
+ }
+
+ public void testUnexpected() throws Exception {
+ doTest(new TheTest("Unexpected TYPE_MISMATCH at 56 to 57") {
+ @Override
+ protected void makeTestData(List diagnostics, List diagnosedRanges) {
+ diagnosedRanges.remove(0);
+ }
+ });
+ }
+
+ public void testBoth() throws Exception {
+ doTest(new TheTest("Unexpected TYPE_MISMATCH at 56 to 57", "Missing UNRESOLVED_REFERENCE at 166 to 168") {
+ @Override
+ protected void makeTestData(List diagnostics, List diagnosedRanges) {
+ diagnosedRanges.remove(0);
+ diagnostics.remove(diagnostics.size() - 1);
+ }
+ });
+ }
+
+ public void testMissingInTheMiddle() throws Exception {
+ doTest(new TheTest("Unexpected NONE_APPLICABLE at 122 to 123", "Missing TYPE_MISMATCH at 161 to 169") {
+ @Override
+ protected void makeTestData(List diagnostics, List diagnosedRanges) {
+ diagnosedRanges.remove(2);
+ diagnostics.remove(diagnostics.size() - 3);
+ }
+ });
+ }
+
+ private static abstract class TheTest {
+ private final String[] expected;
+
+ protected TheTest(String... expectedMessages) {
+ this.expected = expectedMessages;
+ }
+
+ public void test(PsiFile psiFile) {
+ BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache((JetFile) psiFile);
+ String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString();
+
+ List diagnosedRanges = Lists.newArrayList();
+ CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
+
+ List diagnostics = Lists.newArrayList(bindingContext.getDiagnostics());
+ Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
+
+ makeTestData(diagnostics, diagnosedRanges);
+
+ final List expectedMessages = Lists.newArrayList(expected);
+ final List actualMessages = Lists.newArrayList();
+
+ CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
+ @Override
+ public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
+ String message = "Missing " + type + " at " + expectedStart + " to " + expectedEnd;
+ actualMessages.add(message);
+ }
+
+ @Override
+ public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) {
+ String message = "Unexpected " + type + " at " + actualStart + " to " + actualEnd;
+ actualMessages.add(message);
+ }
+ });
+
+ assertEquals(listToString(expectedMessages), listToString(actualMessages));
+ }
+
+ private String listToString(List expectedMessages) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (String expectedMessage : expectedMessages) {
+ stringBuilder.append(expectedMessage).append("\n");
+ }
+ return stringBuilder.toString();
+ }
+
+ protected abstract void makeTestData(List diagnostics, List diagnosedRanges);
+ }
+
+}
diff --git a/idea/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java b/idea/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java
new file mode 100644
index 00000000000..f9c0f0545c8
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java
@@ -0,0 +1,72 @@
+package org.jetbrains.jet.checkers;
+
+import com.google.common.collect.Lists;
+import com.intellij.openapi.util.TextRange;
+import junit.framework.Test;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.JetLiteFixture;
+import org.jetbrains.jet.JetTestCaseBase;
+import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
+import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
+import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.jet.lang.resolve.ImportingStrategy;
+
+import java.util.List;
+
+/**
+ * @author abreslav
+ */
+public class QuickJetPsiCheckerTest extends JetLiteFixture {
+ private String name;
+
+ public QuickJetPsiCheckerTest(@NonNls String dataPath, String name) {
+ super(dataPath);
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return "test" + name;
+ }
+
+ @Override
+ public void runTest() throws Exception {
+ String expectedText = loadFile(name + ".jet");
+ List diagnosedRanges = Lists.newArrayList();
+ String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
+
+ createAndCheckPsiFile(name, clearText);
+ JetFile jetFile = (JetFile) myFile;
+ BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache(jetFile);
+
+ CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
+ @Override
+ public void missingDiagnostic(String type, int expectedStart, int expectedEnd) {
+ String message = "Missing " + type + DiagnosticUtils.atLocation(myFile, new TextRange(expectedStart, expectedEnd));
+ System.err.println(message);
+ }
+
+ @Override
+ public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) {
+ String message = "Unexpected " + type + DiagnosticUtils.atLocation(myFile, new TextRange(actualStart, actualEnd));
+ System.err.println(message);
+ }
+ });
+
+ String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString();
+
+ assertEquals(expectedText, actualText);
+ }
+
+ public static Test suite() {
+ return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/quick", true, new JetTestCaseBase.NamedTestFactory() {
+ @NotNull
+ @Override
+ public Test createTest(@NotNull String dataPath, @NotNull String name) {
+ return new QuickJetPsiCheckerTest(dataPath, name);
+ }
+ });
+ }
+}
diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java
index c5b220f1309..d3678955b79 100644
--- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java
+++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java
@@ -143,42 +143,6 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
doTest(path, true, false);
}
-// public void testBasic() throws Exception {
-// doTest("/resolve/Basic.jet", true, true);
-// }
-//
-// public void testResolveToJava() throws Exception {
-// doTest("/resolve/ResolveToJava.jet", true, true);
-// }
-//
-// public void testResolveOfInfixExpressions() throws Exception {
-// doTest("/resolve/ResolveOfInfixExpressions.jet", true, true);
-// }
-//
-// public void testProjections() throws Exception {
-// doTest("/resolve/Projections.jet", true, true);
-// }
-//
-// public void testPrimaryConstructors() throws Exception {
-// doTest("/resolve/PrimaryConstructors.jet", true, true);
-// }
-//
-// public void testClassifiers() throws Exception {
-// doTest("/resolve/Classifiers.jet", true, true);
-// }
-//
-// public void testConstructorsAndInitializers() throws Exception {
-// doTest("/resolve/ConstructorsAndInitializers.jet", true, true);
-// }
-//
-// public void testNamespaces() throws Exception {
-// doTest("/resolve/Namespaces.jet", true, true);
-// }
-//
-// public void testTryCatch() throws Exception {
-// doTest("/resolve/TryCatch.jet", true, true);
-// }
-
public static Test suite() {
return JetTestCaseBase.suiteForDirectory(getHomeDirectory() + "/idea/testData/", "/resolve/", true, new JetTestCaseBase.NamedTestFactory() {
@NotNull