namespace-level functions supported + tests for resolve to Java
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user