Completion for top-level functions from class and jar files.
This commit is contained in:
@@ -24,18 +24,8 @@ import com.google.inject.Inject;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.Configuration;
|
import org.jetbrains.jet.lang.Configuration;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetImportDirective;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -45,13 +35,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.CANNOT_BE_IMPORTED;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.CANNOT_IMPORT_FROM_ELEMENT;
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.NO_CLASS_OBJECT;
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_HIDDEN_IMPORT;
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_SIMPLE_IMPORT;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -166,7 +150,10 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Collection<? extends DeclarationDescriptor> analyseImportReference(@NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull BindingTrace trace) {
|
public static Collection<? extends DeclarationDescriptor> analyseImportReference(
|
||||||
|
@NotNull JetImportDirective importDirective,
|
||||||
|
@NotNull JetScope scope, @NotNull BindingTrace trace
|
||||||
|
) {
|
||||||
ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(trace, false);
|
ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(trace, false);
|
||||||
return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING);
|
return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.plugin.caches;
|
package org.jetbrains.jet.plugin.caches;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
|
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
|
||||||
@@ -24,8 +25,11 @@ import com.intellij.psi.search.GlobalSearchScope;
|
|||||||
import com.intellij.psi.search.PsiShortNamesCache;
|
import com.intellij.psi.search.PsiShortNamesCache;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import jet.runtime.typeinfo.JetValueParameter;
|
import jet.runtime.typeinfo.JetValueParameter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.JetValueParameterAnnotation;
|
import org.jetbrains.jet.lang.resolve.java.kt.JetValueParameterAnnotation;
|
||||||
|
import org.jetbrains.jet.util.QualifiedNamesUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -33,8 +37,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get jet declarations from java that could be used in completion. Unlike the real jet resolver this helper is allowed
|
* Number of helper methods for searching jet element prototypes in java. Methods use java indices for search.
|
||||||
* to return partially unresolved descriptors in exchange of execution speed.
|
|
||||||
*
|
*
|
||||||
* @author Nikolay Krasko
|
* @author Nikolay Krasko
|
||||||
*/
|
*/
|
||||||
@@ -47,6 +50,9 @@ class JetFromJavaDescriptorHelper {
|
|||||||
* Get java equivalents for jet top level classes.
|
* Get java equivalents for jet top level classes.
|
||||||
*/
|
*/
|
||||||
static PsiClass[] getClassesForJetNamespaces(Project project, GlobalSearchScope scope) {
|
static PsiClass[] getClassesForJetNamespaces(Project project, GlobalSearchScope scope) {
|
||||||
|
/* Will iterate through short name caches
|
||||||
|
Kotlin namespaces from jar a class files will be collected from java cache
|
||||||
|
Kotlin namespaces classes from sources will be collected with JetShortNamesCache.getClassesByName */
|
||||||
return PsiShortNamesCache.getInstance(project).getClassesByName(JvmAbi.PACKAGE_CLASS, scope);
|
return PsiShortNamesCache.getInstance(project).getClassesByName(JvmAbi.PACKAGE_CLASS, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +102,51 @@ class JetFromJavaDescriptorHelper {
|
|||||||
return extensionNames;
|
return extensionNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Collection<PsiMethod> getTopExtensionFunctionByName(String name, Project project, GlobalSearchScope scope) {
|
static Collection<PsiMethod> getTopExtensionFunctionPrototypesByName(String name, Project project, GlobalSearchScope scope) {
|
||||||
|
return filterJetJavaPrototypesByName(
|
||||||
|
name, project, scope,
|
||||||
|
new Predicate<JetValueParameterAnnotation>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable JetValueParameterAnnotation jetValueParameterAnnotation) {
|
||||||
|
assert jetValueParameterAnnotation != null;
|
||||||
|
return jetValueParameterAnnotation.receiver();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static Collection<PsiMethod> getTopLevelFunctionPrototypesByName(String name, Project project, GlobalSearchScope scope) {
|
||||||
|
return filterJetJavaPrototypesByName(
|
||||||
|
name, project, scope,
|
||||||
|
new Predicate<JetValueParameterAnnotation>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable JetValueParameterAnnotation jetValueParameterAnnotation) {
|
||||||
|
assert jetValueParameterAnnotation != null;
|
||||||
|
return !jetValueParameterAnnotation.receiver();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static String getJetTopLevelDeclarationFQN(@NotNull PsiMethod method) {
|
||||||
|
PsiClass containingClass = method.getContainingClass();
|
||||||
|
|
||||||
|
if (containingClass != null) {
|
||||||
|
String classFQN = containingClass.getQualifiedName();
|
||||||
|
|
||||||
|
if (classFQN != null) {
|
||||||
|
if (QualifiedNamesUtil.fqnToShortName(classFQN).equals(JvmAbi.PACKAGE_CLASS)) {
|
||||||
|
String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN);
|
||||||
|
return QualifiedNamesUtil.combine(classParentFQN, method.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<PsiMethod> filterJetJavaPrototypesByName(
|
||||||
|
String name, Project project, GlobalSearchScope scope,
|
||||||
|
Predicate<JetValueParameterAnnotation> filterPredicate) {
|
||||||
Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
|
Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
|
||||||
|
|
||||||
Collection<PsiMethod> psiMethods = JavaMethodNameIndex.getInstance().get(name, project, scope);
|
Collection<PsiMethod> psiMethods = JavaMethodNameIndex.getInstance().get(name, project, scope);
|
||||||
@@ -121,7 +170,7 @@ class JetFromJavaDescriptorHelper {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new JetValueParameterAnnotation(psiAnnotation).receiver()) {
|
if (filterPredicate.apply(new JetValueParameterAnnotation(psiAnnotation))) {
|
||||||
selectedMethods.add(psiMethod);
|
selectedMethods.add(psiMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,12 +34,11 @@ import org.jetbrains.annotations.NonNls;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.asJava.JavaElementFinder;
|
import org.jetbrains.jet.asJava.JavaElementFinder;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.ImportsResolver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
||||||
@@ -157,15 +156,36 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Collection<SimpleFunctionDescriptor> getTopLevelFunctionDescriptorsByName(@NotNull String name,
|
public Collection<FunctionDescriptor> getTopLevelFunctionDescriptorsByName(
|
||||||
@NotNull GlobalSearchScope scope) {
|
@NotNull String name,
|
||||||
|
@NotNull JetSimpleNameExpression expression,
|
||||||
|
@NotNull GlobalSearchScope scope
|
||||||
|
) {
|
||||||
|
HashSet<FunctionDescriptor> result = new HashSet<FunctionDescriptor>();
|
||||||
|
|
||||||
|
JetFile jetFile = (JetFile) expression.getContainingFile();
|
||||||
|
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
|
||||||
|
JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
||||||
|
|
||||||
|
if (jetScope == null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName(name, project, scope);
|
||||||
|
for (PsiMethod method : topLevelFunctionPrototypes) {
|
||||||
|
String functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
|
||||||
|
if (functionFQN != null) {
|
||||||
|
JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, functionFQN);
|
||||||
|
Collection<? extends DeclarationDescriptor> declarationDescriptors = ImportsResolver.analyseImportReference(importDirective, jetScope, new BindingTraceContext());
|
||||||
|
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
|
||||||
|
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||||
|
result.add((FunctionDescriptor) declarationDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||||
|
|
||||||
BindingContext context = getResolutionContext(scope);
|
|
||||||
|
|
||||||
HashSet<SimpleFunctionDescriptor> result = new HashSet<SimpleFunctionDescriptor>();
|
|
||||||
|
|
||||||
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
|
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
|
||||||
SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
|
SimpleFunctionDescriptor functionDescriptor = context.get(BindingContext.FUNCTION, jetNamedFunction);
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
@@ -204,7 +224,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
public Collection<PsiElement> getJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
|
public Collection<PsiElement> getJetExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
|
||||||
HashSet<PsiElement> functions = new HashSet<PsiElement>();
|
HashSet<PsiElement> functions = new HashSet<PsiElement>();
|
||||||
functions.addAll(JetExtensionFunctionNameIndex.getInstance().get(name, project, scope));
|
functions.addAll(JetExtensionFunctionNameIndex.getInstance().get(name, project, scope));
|
||||||
functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionByName(name, project, scope));
|
functions.addAll(JetFromJavaDescriptorHelper.getTopExtensionFunctionPrototypesByName(name, project, scope));
|
||||||
|
|
||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
@@ -217,10 +237,6 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
) {
|
) {
|
||||||
Collection<DeclarationDescriptor> resultDescriptors = new ArrayList<DeclarationDescriptor>();
|
Collection<DeclarationDescriptor> resultDescriptors = new ArrayList<DeclarationDescriptor>();
|
||||||
|
|
||||||
if (!(expression.getContainingFile() instanceof JetFile)) {
|
|
||||||
return resultDescriptors;
|
|
||||||
}
|
|
||||||
|
|
||||||
JetFile jetFile = (JetFile) expression.getContainingFile();
|
JetFile jetFile = (JetFile) expression.getContainingFile();
|
||||||
|
|
||||||
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
|
BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(jetFile);
|
||||||
@@ -245,16 +261,9 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction));
|
functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction));
|
||||||
}
|
}
|
||||||
else if (extensionFunction instanceof PsiMethod) {
|
else if (extensionFunction instanceof PsiMethod) {
|
||||||
PsiMethod function = (PsiMethod) extensionFunction;
|
String functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN((PsiMethod) extensionFunction);
|
||||||
PsiClass containingClass = function.getContainingClass();
|
if (functionFQN != null) {
|
||||||
|
functionFQNs.add(functionFQN);
|
||||||
if (containingClass != null) {
|
|
||||||
String classFQN = containingClass.getQualifiedName();
|
|
||||||
|
|
||||||
if (classFQN != null) {
|
|
||||||
String classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN);
|
|
||||||
functionFQNs.add(QualifiedNamesUtil.combine(classParentFQN, function.getName()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,7 +288,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
|||||||
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> getAllJetFunctionsNames() {
|
public Collection<String> getAllJetOnlyTopFunctionsNames() {
|
||||||
return JetShortFunctionNameIndex.getInstance().getAllKeys(project);
|
return JetShortFunctionNameIndex.getInstance().getAllKeys(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import java.util.Set;
|
|||||||
* @author Nikolay Krasko
|
* @author Nikolay Krasko
|
||||||
*/
|
*/
|
||||||
public class JetCompletionContributor extends CompletionContributor {
|
public class JetCompletionContributor extends CompletionContributor {
|
||||||
|
|
||||||
public JetCompletionContributor() {
|
public JetCompletionContributor() {
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(),
|
extend(CompletionType.BASIC, PlatformPatterns.psiElement(),
|
||||||
new CompletionProvider<CompletionParameters>() {
|
new CompletionProvider<CompletionParameters>() {
|
||||||
@@ -86,7 +87,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
|
|
||||||
if (shouldRunTopLevelCompletion(parameters, prefix)) {
|
if (shouldRunTopLevelCompletion(parameters, prefix)) {
|
||||||
addClasses(parameters, result);
|
addClasses(parameters, result);
|
||||||
addJetTopLevelFunctions(result, position, positions);
|
addJetTopLevelFunctions(jetReference.getExpression(), result, position, positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldRunExtensionsCompletion(parameters, prefix)) {
|
if (shouldRunExtensionsCompletion(parameters, prefix)) {
|
||||||
@@ -132,7 +133,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position,
|
private static void addJetTopLevelFunctions(JetSimpleNameExpression expression, @NotNull CompletionResultSet result, @NotNull PsiElement position,
|
||||||
@NotNull Set<LookupPositionObject> positions) {
|
@NotNull Set<LookupPositionObject> positions) {
|
||||||
|
|
||||||
String actualPrefix = result.getPrefixMatcher().getPrefix();
|
String actualPrefix = result.getPrefixMatcher().getPrefix();
|
||||||
@@ -147,7 +148,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
|||||||
|
|
||||||
for (String name : functionNames) {
|
for (String name : functionNames) {
|
||||||
if (name.contains(actualPrefix)) {
|
if (name.contains(actualPrefix)) {
|
||||||
for (FunctionDescriptor function : namesCache.getTopLevelFunctionDescriptorsByName(name, scope)) {
|
for (FunctionDescriptor function : namesCache.getTopLevelFunctionDescriptorsByName(name, expression, scope)) {
|
||||||
addCompletionToResult(result, DescriptorLookupConverter.createLookupElement(resolutionContext, function), positions);
|
addCompletionToResult(result, DescriptorLookupConverter.createLookupElement(resolutionContext, function), positions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package testing
|
||||||
|
|
||||||
|
fun someFun() {
|
||||||
|
measureTime<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Important: This test checks that completion will find top level functions from jars.
|
||||||
|
// If you going to update it make sure that methods are not auto-imported
|
||||||
|
|
||||||
|
// RUNTIME: 1
|
||||||
|
// EXIST: measureTimeNano, measureTimeMillis
|
||||||
@@ -105,6 +105,10 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testTopLevelFromStandardLibrary() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
public void testVariableClassName() {
|
public void testVariableClassName() {
|
||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user