namespace-level functions supported + tests for resolve to Java

This commit is contained in:
Andrey Breslav
2011-03-09 16:17:28 +03:00
parent db9c36adb0
commit 4d574402ed
12 changed files with 236 additions and 145 deletions
@@ -10,15 +10,11 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.*;
/**
* @author abreslav
@@ -28,16 +24,24 @@ public class ExpectedResolveData {
private final Map<String, Integer> declarationToPosition = new HashMap<String, Integer>();
private final Map<Integer, String> positionToReference = new HashMap<Integer, String>();
private final Map<Integer, String> positionToType = new HashMap<Integer, String>();
private final Map<String, DeclarationDescriptor> nameToDescriptor;
private final Map<String, PsiElement> nameToPsiElement;
public ExpectedResolveData(final Document document) {
public ExpectedResolveData(Map<String, DeclarationDescriptor> nameToDescriptor, Map<String, PsiElement> nameToPsiElement) {
this.nameToDescriptor = nameToDescriptor;
this.nameToPsiElement = nameToPsiElement;
}
public void extractData(final Document document) {
new WriteCommandAction.Simple(null) {
public void run() {
extractData(document);
doExtractData(document);
}
}.execute().throwException();
}
private void extractData(Document document) {
private void doExtractData(Document document) {
String text = document.getText();
Pattern pattern = Pattern.compile("(~[^~]+~)|(`[^`]+`)");
@@ -71,12 +75,16 @@ public class ExpectedResolveData {
}
public void checkResult(JetFile file) {
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(file.getProject(), ErrorHandler.THROW_EXCEPTION);
final Set<PsiElement> unresolvedReferences = new HashSet<PsiElement>();
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(file.getProject(), new ErrorHandler() {
@Override
public void unresolvedReference(JetReferenceExpression referenceExpression) {
unresolvedReferences.add(referenceExpression.getReferencedNameElement());
}
});
JetStandardLibrary lib = semanticServices.getStandardLibrary();
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, ErrorHandler.THROW_EXCEPTION);
BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, semanticServices.getErrorHandler());
Map<String, JetDeclaration> nameToDeclaration = new HashMap<String, JetDeclaration>();
@@ -96,7 +104,15 @@ public class ExpectedResolveData {
String name = entry.getValue();
PsiElement element = file.findElementAt(position);
JetDeclaration expected = nameToDeclaration.get(name);
if ("!".equals(name)) {
assertTrue("Must have been unresolved: " + element, unresolvedReferences.contains(element));
continue;
}
PsiElement expected = nameToDeclaration.get(name);
if (expected == null) {
expected = nameToPsiElement.get(name);
}
JetReferenceExpression reference = getAncestorOfType(JetReferenceExpression.class, element);
if (expected == null && name.startsWith("std::")) {
@@ -158,17 +174,6 @@ public class ExpectedResolveData {
}
}
private DeclarationDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) {
FunctionGroup functionGroup = classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()).getFunctionGroup(name);
Collection<FunctionDescriptor> functions = functionGroup.getPossiblyApplicableFunctions(Collections.<Type>emptyList(), Collections.singletonList(parameterType));
for (FunctionDescriptor function : functions) {
if (function.getUnsubstitutedValueParameters().get(0).getType().equals(parameterType)) {
return function;
}
}
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterType + ")");
}
private <T> T getAncestorOfType(Class<T> type, PsiElement element) {
while (element != null && !type.isInstance(element)) {
element = element.getParent();
@@ -28,17 +28,21 @@ import java.util.List;
*/
public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase {
private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
private ExpectedResolveData expectedResolveData;
@Override
protected void setUp() throws Exception {
super.setUp();
expectedResolveData = getExpectedResolveData();
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).prepareForTest(true);
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
}
protected abstract ExpectedResolveData getExpectedResolveData();
@Override
protected void tearDown() throws Exception {
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(true); // has to cleanup by hand since light project does not get disposed any time soon
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(); // has to cleanup by hand since light project does not get disposed any time soon
super.tearDown();
}
@@ -69,7 +73,7 @@ public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
// ExpectedHighlightingData expectedData = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos);
ExpectedResolveData expectedData = new ExpectedResolveData(getEditor().getDocument());
expectedResolveData.extractData(getEditor().getDocument());
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
getFile().getText(); //to load text
@@ -80,7 +84,7 @@ public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
expectedData.checkResult((JetFile) getFile());
expectedResolveData.checkResult((JetFile) getFile());
}
@NotNull
@@ -1,9 +1,21 @@
package org.jetbrains.jet.resolve;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
/**
* @author abreslav
@@ -11,8 +23,55 @@ import java.io.File;
public class JetResolveTest extends ExtensibleResolveTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
protected ExpectedResolveData getExpectedResolveData() {
Project project = getProject();
JetStandardLibrary lib = JetStandardLibrary.getJetStandardLibrary(project);
Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>();
nameToDescriptor.put("std::Int.plus(Int)", standardFunction(lib.getInt(), "plus", lib.getIntType()));
Map<String,PsiElement> nameToDeclaration = new HashMap<String, PsiElement>();
nameToDeclaration.put("java::java.util.Collections.emptyList()", findMethod(findClass(project, "java.util.Collections"), "emptyList"));
nameToDeclaration.put("java::java.util.Collections", findClass(project, "java.util.Collections"));
nameToDeclaration.put("java::java.util.List", findClass(project, "java.util.List"));
nameToDeclaration.put("java::java", findPackage(project, "java"));
nameToDeclaration.put("java::java.util", findPackage(project, "java.util"));
nameToDeclaration.put("java::java.lang", findPackage(project, "java.lang"));
nameToDeclaration.put("java::java.lang.Object", findClass(project, "java.lang.Object"));
nameToDeclaration.put("java::java.lang.System", findClass(project, "java.lang.System"));
PsiMethod[] methods = findClass(project, "java.io.PrintStream").findMethodsByName("print", true);
nameToDeclaration.put("java::java.io.PrintStream.print(Object)", methods[8]);
nameToDeclaration.put("java::java.io.PrintStream.print(Int)", methods[2]);
nameToDeclaration.put("java::java.lang.System.out", findClass(project, "java.lang.System").findFieldByName("out", true));
return new ExpectedResolveData(nameToDescriptor, nameToDeclaration);
}
private PsiElement findPackage(Project project, String qualifiedName) {
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(project);
return javaFacade.findPackage(qualifiedName);
}
private PsiMethod findMethod(PsiClass collections, String name) {
PsiMethod[] emptyLists = collections.findMethodsByName(name, true);
return emptyLists[0];
}
private PsiClass findClass(Project project, String qualifiedName) {
JavaPsiFacade javaFacade = JavaPsiFacade.getInstance(project);
GlobalSearchScope javaSearchScope = GlobalSearchScope.allScope(project);
return javaFacade.findClass(qualifiedName, javaSearchScope);
}
private DeclarationDescriptor standardFunction(ClassDescriptor classDescriptor, String name, Type parameterType) {
FunctionGroup functionGroup = classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList()).getFunctionGroup(name);
Collection<FunctionDescriptor> functions = functionGroup.getPossiblyApplicableFunctions(Collections.<Type>emptyList(), Collections.singletonList(parameterType));
for (FunctionDescriptor function : functions) {
if (function.getUnsubstitutedValueParameters().get(0).getType().equals(parameterType)) {
return function;
}
}
throw new IllegalArgumentException("Not found: std::" + classDescriptor.getName() + "." + name + "(" + parameterType + ")");
}
@Override
@@ -20,6 +79,18 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
return getHomeDirectory() + "/idea/testData";
}
@Override
protected Sdk getProjectJDK() {
Properties properties = new Properties();
try {
properties.load(new FileReader(getHomeDirectory() + "/idea/idea.properties"));
} catch (IOException e) {
throw new RuntimeException(e);
}
String home = properties.getProperty("idea.home");
return new JavaSdkImpl().createJdk("JDK", home + "/java/mockJDK-1.7/jre", true);
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
}
@@ -28,4 +99,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
doTest("/resolve/Basic.jet", true, true);
}
public void testResolveToJava() throws Exception {
doTest("/resolve/ResolveToJava.jet", true, true);
}
}