@NotNull public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty( @NotNull BasicCallResolutionContext context) { JetExpression calleeExpression = context.call.getCalleeExpression(); assert calleeExpression instanceof JetSimpleNameExpression; JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression; Name referencedName = nameExpression.getReferencedNameAsName(); List<CallableDescriptorCollector<? extends VariableDescriptor>> callableDescriptorCollectors = Lists.newArrayList(); if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { referencedName = Name.identifier(referencedName.asString().substring(1)); callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES); } else { callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES); } List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks = TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks( context, referencedName, nameExpression, callableDescriptorCollectors); return doResolveCallOrGetCachedResults( ResolutionResultsCache.PROPERTY_MEMBER_TYPE, context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression); }
public void testMultiPackageFunction() { myFixture.configureByText( JetFileType.INSTANCE, "package test.testing\n" + "fun other(v : Int) = 12\n" + "fun other(v : String) {}"); StubPackageMemberDeclarationProvider provider = new StubPackageMemberDeclarationProvider( new FqName("test.testing"), getProject(), GlobalSearchScope.projectScope(getProject())); List<JetNamedFunction> other = Lists.newArrayList(provider.getFunctionDeclarations(Name.identifier("other"))); Collection<String> functionTexts = Collections2.transform( other, new Function<JetNamedFunction, String>() { @Override public String apply(JetNamedFunction function) { return function.getText(); } }); assertSize(2, other); assertTrue(functionTexts.contains("fun other(v : Int) = 12")); assertTrue(functionTexts.contains("fun other(v : String) {}")); }
@NotNull private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> getSuperclassToFunctionsMultimap( @NotNull PsiMethodWrapper method, @NotNull BindingContext bindingContext, @NotNull ClassDescriptor containingClass) { Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create(); Name functionName = Name.identifier(method.getName()); int parameterCount = method.getParameters().size(); for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) { ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor(); assert klass != null; FqName fqName = DescriptorUtils.getFQName(klass).toSafe(); for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) { if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) { PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun); if (declaration instanceof PsiMethod) { result.put(fqName, Pair.create(fun, (PsiMethod) declaration)); } // else declaration is null or JetNamedFunction: both cases are processed later } } } return result; }
@NotNull @Override protected Collection<DeclarationDescriptor> computeAllDescriptors() { Collection<DeclarationDescriptor> result = super.computeAllDescriptors(); for (PsiClass nested : declarationProvider.getPsiClass().getInnerClasses()) { ContainerUtil.addIfNotNull(result, getNamespace(Name.identifier(nested.getName()))); } return result; }
@NotNull public static SimpleFunctionDescriptor createSamConstructorFunction( @NotNull ClassOrNamespaceDescriptor owner, @NotNull ClassDescriptor samInterface) { assert isSamInterface(samInterface) : samInterface; SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl( owner, samInterface.getAnnotations(), samInterface.getName(), CallableMemberDescriptor.Kind.SYNTHESIZED); TypeParameters typeParameters = recreateAndInitializeTypeParameters( samInterface.getTypeConstructor().getParameters(), result); JetType parameterTypeUnsubstituted = getFunctionTypeForSamType(samInterface.getDefaultType()); JetType parameterType = typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE); assert parameterType != null : "couldn't substitute type: " + parameterType + ", substitutor = " + typeParameters.substitutor; ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl( result, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("function"), parameterType, false, null); JetType returnType = typeParameters.substitutor.substitute(samInterface.getDefaultType(), Variance.OUT_VARIANCE); assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor; result.initialize( null, null, typeParameters.descriptors, Arrays.asList(parameter), returnType, Modality.FINAL, samInterface.getVisibility(), false); return result; }
public void testSinglePackageFunction() { myFixture.configureByText(JetFileType.INSTANCE, "package test.testing\n" + "fun some() {}"); StubPackageMemberDeclarationProvider provider = new StubPackageMemberDeclarationProvider( new FqName("test.testing"), getProject(), GlobalSearchScope.projectScope(getProject())); List<JetNamedFunction> some = Lists.newArrayList(provider.getFunctionDeclarations(Name.identifier("some"))); assertSize(1, some); assertEquals("fun some() {}", some.get(0).getText()); }
public void testPackageProperty() { myFixture.configureByText(JetFileType.INSTANCE, "package test.testing\n" + "val test = 12\n"); StubPackageMemberDeclarationProvider provider = new StubPackageMemberDeclarationProvider( new FqName("test.testing"), getProject(), GlobalSearchScope.projectScope(getProject())); List<JetProperty> testProperties = Lists.newArrayList(provider.getPropertyDeclarations(Name.identifier("test"))); assertSize(1, testProperties); assertEquals("val test = 12", testProperties.get(0).getText()); }
public static FunctionDescriptor getInvokeFunction(@NotNull JetType functionType) { assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType); ClassifierDescriptor classDescriptorForFunction = functionType.getConstructor().getDeclarationDescriptor(); assert classDescriptorForFunction instanceof ClassDescriptor; Collection<FunctionDescriptor> invokeFunctions = ((ClassDescriptor) classDescriptorForFunction) .getMemberScope(functionType.getArguments()) .getFunctions(Name.identifier("invoke")); assert invokeFunctions.size() == 1; return invokeFunctions.iterator().next(); }
@NotNull private static List<ValueParameterDescriptor> createValueParameterDescriptors( @NotNull ExpressionTypingContext context, @NotNull JetFunctionLiteral functionLiteral, @NotNull FunctionDescriptorImpl functionDescriptor, boolean functionTypeExpected) { List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList(); List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters(); List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected) ? KotlinBuiltIns.getInstance() .getValueParameters(functionDescriptor, context.expectedType) : null; JetParameterList valueParameterList = functionLiteral.getValueParameterList(); boolean hasDeclaredValueParameters = valueParameterList != null; if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) { ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0); ValueParameterDescriptor it = new ValueParameterDescriptorImpl( functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("it"), valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()); valueParameterDescriptors.add(it); context.trace.record(AUTO_CREATED_IT, it); } else { if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) { List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters); context.trace.report( EXPECTED_PARAMETERS_NUMBER_MISMATCH.on( functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); } for (int i = 0; i < declaredValueParameters.size(); i++) { ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor( context, functionDescriptor, declaredValueParameters, expectedValueParameters, i); valueParameterDescriptors.add(valueParameterDescriptor); } } return valueParameterDescriptors; }
@Nullable public static Name getAliasName(@NotNull JetImportDirective importDirective) { String aliasName = importDirective.getAliasName(); JetExpression importedReference = importDirective.getImportedReference(); if (importedReference == null) { return null; } JetSimpleNameExpression referenceExpression = getLastReference(importedReference); if (aliasName == null) { aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null; } return aliasName != null && !aliasName.isEmpty() ? Name.identifier(aliasName) : null; }
@Nullable public static Name getShortName(@NotNull JetAnnotationEntry annotation) { JetTypeReference typeReference = annotation.getTypeReference(); assert typeReference != null : "Annotation entry hasn't typeReference " + annotation.getText(); JetTypeElement typeElement = typeReference.getTypeElement(); if (typeElement instanceof JetUserType) { JetUserType userType = (JetUserType) typeElement; String shortName = userType.getReferencedName(); if (shortName != null) { return Name.identifier(shortName); } } return null; }
@NotNull private static ClassDescriptor createClass( @NotNull PackageFragmentDescriptor packageFragment, @NotNull String name, @NotNull String... typeParameters) { MutableClassDescriptor descriptor = new MutableClassDescriptor( packageFragment, packageFragment.getMemberScope(), ClassKind.CLASS, false, Name.identifier(name)); List<TypeParameterDescriptor> typeParameterDescriptors = new ArrayList<TypeParameterDescriptor>(typeParameters.length); for (int i = 0; i < typeParameters.length; i++) { String[] s = typeParameters[i].split(" "); Variance variance = Variance.valueOf(s[0].toUpperCase() + "_VARIANCE"); String typeParameterName = s[1]; TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification( descriptor, Annotations.EMPTY, false, variance, Name.identifier(typeParameterName), i); typeParameter.setInitialized(); typeParameterDescriptors.add(typeParameter); } descriptor.setModality(Modality.FINAL); descriptor.setVisibility(Visibilities.PUBLIC); descriptor.setTypeParameterDescriptors(typeParameterDescriptors); descriptor.createTypeConstructor(); return descriptor; }
@Nullable static FqName getJetTopLevelDeclarationFQN(@NotNull PsiMethod method) { PsiClass containingClass = method.getContainingClass(); if (containingClass != null) { String qualifiedName = containingClass.getQualifiedName(); assert qualifiedName != null; FqName classFQN = new FqName(qualifiedName); if (JavaResolverPsiUtils.isCompiledKotlinPackageClass(containingClass)) { FqName classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN); return QualifiedNamesUtil.combine(classParentFQN, Name.identifier(method.getName())); } } return null; }
private void processFields() { // Hack to load static members for enum class loaded from class file if (kotlin && !psiClass.getPsiClass().isEnum()) { return; } for (PsiField field0 : psiClass.getPsiClass().getAllFields()) { PsiFieldWrapper field = new PsiFieldWrapper(field0); // group must be created even for excluded field NamedMembers namedMembers = getNamedMembers(Name.identifier(field.getName())); if (!includeMember(field)) { continue; } TypeSource type = new TypeSource("", field.getType(), field0); namedMembers.addPropertyAccessor(new PropertyAccessorData(field, type, null)); } }
@NotNull public static NamespaceDescriptor compileJava( @NotNull Collection<File> javaFiles, File tmpdir, Disposable disposable) throws IOException { JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, Locale.ENGLISH, Charset.forName("utf-8")); try { Iterable<? extends JavaFileObject> javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(javaFiles); List<String> options = Arrays.asList( "-classpath", "out/production/runtime" + File.pathSeparator + JetTestUtils.getAnnotationsJar().getPath(), "-d", tmpdir.getPath()); JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, javaFileObjectsFromFiles); Assert.assertTrue(task.call()); } finally { fileManager.close(); } JetCoreEnvironment jetCoreEnvironment = new JetCoreEnvironment( disposable, CompileCompilerDependenciesTest.compilerConfigurationForTests( ConfigurationKind.JDK_ONLY, TestJdkKind.MOCK_JDK, JetTestUtils.getAnnotationsJar(), tmpdir, new File("out/production/runtime"))); InjectorForJavaSemanticServices injector = new InjectorForJavaSemanticServices( BuiltinsScopeExtensionMode.ALL, jetCoreEnvironment.getProject()); JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); return javaDescriptorResolver.resolveNamespace( FqName.topLevel(Name.identifier("test")), DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); }
@Nullable @IfNotParsed public static ImportPath getImportPath(@NotNull JetImportDirective importDirective) { if (PsiTreeUtil.hasErrorElements(importDirective)) { return null; } FqName importFqn = getFQName(importDirective.getImportedReference()); if (importFqn == null) { return null; } Name alias = null; String aliasName = importDirective.getAliasName(); if (aliasName != null) { alias = Name.identifier(aliasName); } return new ImportPath(importFqn, importDirective.isAllUnder(), alias); }
public static SimpleFunctionDescriptor createInvoke(FunctionDescriptor fd) { int arity = fd.getValueParameters().size(); SimpleFunctionDescriptorImpl invokeDescriptor = new SimpleFunctionDescriptorImpl( fd.getExpectedThisObject().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity), Collections.<AnnotationDescriptor>emptyList(), Name.identifier("invoke"), CallableMemberDescriptor.Kind.DECLARATION); invokeDescriptor.initialize( fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, fd.getExpectedThisObject(), Collections.<TypeParameterDescriptorImpl>emptyList(), fd.getValueParameters(), fd.getReturnType(), Modality.FINAL, Visibilities.PUBLIC, /*isInline = */ false); return invokeDescriptor; }
@Nullable private CompileTimeConstant<?> getCompileTimeConstFromReferenceExpression( PsiReferenceExpression value, PostponedTasks taskList) { PsiElement resolveElement = value.resolve(); if (resolveElement instanceof PsiEnumConstant) { PsiElement psiElement = resolveElement.getParent(); if (psiElement instanceof PsiClass) { PsiClass psiClass = (PsiClass) psiElement; String fqName = psiClass.getQualifiedName(); if (fqName == null) { return null; } JetScope scope; ClassDescriptor classDescriptor = classResolver.resolveClass( new FqName(fqName), DescriptorSearchRule.INCLUDE_KOTLIN, taskList); if (classDescriptor == null) { return null; } ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor(); if (classObjectDescriptor == null) { return null; } scope = classObjectDescriptor.getMemberScope(Lists.<TypeProjection>newArrayList()); Name identifier = Name.identifier(((PsiEnumConstant) resolveElement).getName()); Collection<VariableDescriptor> properties = scope.getProperties(identifier); for (VariableDescriptor variableDescriptor : properties) { if (variableDescriptor.getReceiverParameter() == null) { return new EnumValue((PropertyDescriptor) variableDescriptor); } } return null; } } return null; }
@Test public void testJetStandardLibrary() throws Exception { List<JetFile> files = Lists.newArrayList(); addJetFilesFromDir(files, new File("compiler/frontend/src/jet")); final Map<FqName, Name> aliases = ImmutableMap.<FqName, Name>builder() .put(new FqName("jet.Unit"), Name.identifier("Tuple0")) .build(); ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("<lazy module>")); ResolveSession session = new ResolveSession( getProject(), lazyModule, new SpecialModuleConfiguration(), new FileBasedDeclarationProviderFactory(files), new Function<FqName, Name>() { @Override public Name fun(FqName name) { return aliases.get(name); } }, Predicates.in( Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing"))), new BindingTraceContext()); NamespaceDescriptor jetNamespaceFromJSL = (NamespaceDescriptor) KotlinBuiltIns.getInstance().getInt().getContainingDeclaration(); NamespaceDescriptor jetNamespaceFromLazy = lazyModule.getRootNamespace().getMemberScope().getNamespace(jetNamespaceFromJSL.getName()); NamespaceComparator.compareNamespaces( jetNamespaceFromJSL, jetNamespaceFromLazy, NamespaceComparator.RECURSIVE, new File("compiler/testData/builtin-classes.txt")); }
protected AccessorForPropertyDescriptor( @NotNull PropertyDescriptor original, @NotNull JetType propertyType, @Nullable JetType receiverType, @Nullable ReceiverParameterDescriptor expectedThisObject, @NotNull DeclarationDescriptor containingDeclaration, int index) { super( containingDeclaration, Annotations.EMPTY, Modality.FINAL, Visibilities.LOCAL, original.isVar(), Name.identifier(original.getName() + "$b$" + index), Kind.DECLARATION); setType( propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), expectedThisObject, receiverType); initialize(new Getter(this), new Setter(this)); }
public AccessorForFunctionDescriptor( @NotNull FunctionDescriptor descriptor, @NotNull DeclarationDescriptor containingDeclaration, int index) { super( containingDeclaration, Annotations.EMPTY, Name.identifier( (descriptor instanceof ConstructorDescriptor ? "$init" : descriptor.getName()) + "$b$" + index), Kind.DECLARATION); initialize( DescriptorUtils.getReceiverParameterType(descriptor.getReceiverParameter()), descriptor instanceof ConstructorDescriptor ? NO_RECEIVER_PARAMETER : descriptor.getExpectedThisObject(), Collections.<TypeParameterDescriptor>emptyList(), copyValueParameters(descriptor), descriptor.getReturnType(), Modality.FINAL, Visibilities.INTERNAL); }
@NotNull public static Name safeName(@Nullable String name) { return name == null ? SpecialNames.NO_NAME_PROVIDED : Name.identifier(name); }
public final class JavaAnnotationResolver { public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); public static final FqName JETBRAINS_NOT_NULL_ANNOTATION = fqNameByClass(NotNull.class); public static final FqName JETBRAINS_MUTABLE_ANNOTATION = new FqName("org.jetbrains.annotations.Mutable"); public static final FqName JETBRAINS_READONLY_ANNOTATION = new FqName("org.jetbrains.annotations.ReadOnly"); private JavaClassResolver classResolver; private JavaAnnotationArgumentResolver argumentResolver; private ExternalAnnotationResolver externalAnnotationResolver; public JavaAnnotationResolver() {} @Inject public void setClassResolver(JavaClassResolver classResolver) { this.classResolver = classResolver; } @Inject public void setArgumentResolver(JavaAnnotationArgumentResolver argumentResolver) { this.argumentResolver = argumentResolver; } @Inject public void setExternalAnnotationResolver(ExternalAnnotationResolver externalAnnotationResolver) { this.externalAnnotationResolver = externalAnnotationResolver; } private void resolveAnnotations( @NotNull Collection<JavaAnnotation> annotations, @NotNull PostponedTasks tasks, @NotNull List<AnnotationDescriptor> result) { for (JavaAnnotation javaAnnotation : annotations) { AnnotationDescriptor annotation = resolveAnnotation(javaAnnotation, tasks); if (annotation != null) { result.add(annotation); } } } @NotNull public List<AnnotationDescriptor> resolveAnnotations( @NotNull JavaAnnotationOwner owner, @NotNull PostponedTasks tasks) { List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>(); resolveAnnotations(owner.getAnnotations(), tasks, result); resolveAnnotations(externalAnnotationResolver.findExternalAnnotations(owner), tasks, result); return result; } @NotNull public List<AnnotationDescriptor> resolveAnnotations(@NotNull JavaAnnotationOwner owner) { PostponedTasks postponedTasks = new PostponedTasks(); List<AnnotationDescriptor> annotations = resolveAnnotations(owner, postponedTasks); postponedTasks.performTasks(); return annotations; } @Nullable public AnnotationDescriptor resolveAnnotation( @NotNull JavaAnnotation javaAnnotation, @NotNull PostponedTasks postponedTasks) { final AnnotationDescriptor annotation = new AnnotationDescriptor(); FqName fqName = javaAnnotation.getFqName(); if (fqName == null) { return null; } // Don't process internal jet annotations and jetbrains NotNull annotations if (fqName.asString().startsWith("jet.runtime.typeinfo.") || fqName.equals(JETBRAINS_NOT_NULL_ANNOTATION) || fqName.equals(JvmAnnotationNames.KOTLIN_CLASS) || fqName.equals(JvmAnnotationNames.KOTLIN_PACKAGE)) { return null; } AnnotationDescriptor mappedClassDescriptor = JavaToKotlinClassMap.getInstance().mapToAnnotationClass(fqName); if (mappedClassDescriptor != null) { return mappedClassDescriptor; } final ClassDescriptor annotationClass = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES, postponedTasks); if (annotationClass == null) { return null; } postponedTasks.addTask( new Runnable() { @Override public void run() { annotation.setAnnotationType(annotationClass.getDefaultType()); } }); for (JavaAnnotationArgument argument : javaAnnotation.getArguments()) { CompileTimeConstant value = argumentResolver.resolveAnnotationArgument(fqName, argument, postponedTasks); if (value == null) continue; Name name = argument.getName(); ValueParameterDescriptor descriptor = DescriptorResolverUtils.getAnnotationParameterByName( name == null ? DEFAULT_ANNOTATION_MEMBER_NAME : name, annotationClass); if (descriptor != null) { annotation.setValueArgument(descriptor, value); } } return annotation; } @Nullable public JavaAnnotation findAnnotationWithExternal( @NotNull JavaAnnotationOwner owner, @NotNull FqName name) { JavaAnnotation annotation = owner.findAnnotation(name); if (annotation != null) { return annotation; } return externalAnnotationResolver.findExternalAnnotation(owner, name); } public boolean hasNotNullAnnotation(@NotNull JavaAnnotationOwner owner) { return findAnnotationWithExternal(owner, JETBRAINS_NOT_NULL_ANNOTATION) != null; } public boolean hasMutableAnnotation(@NotNull JavaAnnotationOwner owner) { return findAnnotationWithExternal(owner, JETBRAINS_MUTABLE_ANNOTATION) != null; } public boolean hasReadonlyAnnotation(@NotNull JavaAnnotationOwner owner) { return findAnnotationWithExternal(owner, JETBRAINS_READONLY_ANNOTATION) != null; } }
private void processMethods() { for (PsiMethod method : psiClass.getPsiClass().getAllMethods()) { getNamedMembers(Name.identifier(method.getName())); PropertyParseResult propertyParseResult = PropertyNameUtils.parseMethodToProperty(method.getName()); if (propertyParseResult != null) { getNamedMembers(Name.identifier(propertyParseResult.getPropertyName())); } } for (PsiMethod method0 : psiClass.getPsiClass().getMethods()) { PsiMethodWrapper method = new PsiMethodWrapper(method0); if (!includeMember(method)) { continue; } PropertyParseResult propertyParseResult = PropertyNameUtils.parseMethodToProperty(method.getName()); // TODO: remove getJavaClass if (propertyParseResult != null && propertyParseResult.isGetter()) { String propertyName = propertyParseResult.getPropertyName(); NamedMembers members = getNamedMembers(Name.identifier(propertyName)); // TODO: some java properties too if (method.getJetMethod().flags().get(JvmStdlibNames.FLAG_PROPERTY_BIT)) { int i = 0; TypeSource receiverType; if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) { PsiParameterWrapper receiverParameter = method.getParameter(i); receiverType = new TypeSource( receiverParameter.getJetValueParameter().type(), receiverParameter.getPsiParameter().getType(), receiverParameter.getPsiParameter()); ++i; } else { receiverType = null; } while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { // TODO: store is reified ++i; } if (i != method.getParameters().size()) { // TODO: report error properly throw new IllegalStateException("something is wrong with method " + method0); } // TODO: what if returnType == null? TypeSource propertyType = new TypeSource( method.getJetMethod().propertyType(), method.getReturnType(), method.getPsiMethod()); members.addPropertyAccessor( new PropertyAccessorData(method, true, propertyType, receiverType)); } else if (!kotlin && false) { if (method.getParameters().size() == 0) { TypeSource propertyType = new TypeSource("", method.getReturnType(), method.getPsiMethod()); members.addPropertyAccessor( new PropertyAccessorData(method, true, propertyType, null)); } } } else if (propertyParseResult != null && !propertyParseResult.isGetter()) { String propertyName = propertyParseResult.getPropertyName(); NamedMembers members = getNamedMembers(Name.identifier(propertyName)); if (method.getJetMethod().flags().get(JvmStdlibNames.FLAG_PROPERTY_BIT)) { if (method.getParameters().size() == 0) { // TODO: report error properly throw new IllegalStateException(); } int i = 0; TypeSource receiverType = null; PsiParameterWrapper p1 = method.getParameter(0); if (p1.getJetValueParameter().receiver()) { receiverType = new TypeSource( p1.getJetValueParameter().type(), p1.getPsiParameter().getType(), p1.getPsiParameter()); ++i; } while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { ++i; } if (i + 1 != method.getParameters().size()) { throw new IllegalStateException(); } PsiParameterWrapper propertyTypeParameter = method.getParameter(i); TypeSource propertyType = new TypeSource( method.getJetMethod().propertyType(), propertyTypeParameter.getPsiParameter().getType(), propertyTypeParameter.getPsiParameter()); members.addPropertyAccessor( new PropertyAccessorData(method, false, propertyType, receiverType)); } else if (!kotlin && false) { if (method.getParameters().size() == 1) { PsiParameter psiParameter = method.getParameters().get(0).getPsiParameter(); TypeSource propertyType = new TypeSource("", psiParameter.getType(), psiParameter); members.addPropertyAccessor( new PropertyAccessorData(method, false, propertyType, null)); } } } if (!method.getJetMethod().flags().get(JvmStdlibNames.FLAG_PROPERTY_BIT)) { NamedMembers namedMembers = getNamedMembers(Name.identifier(method.getName())); namedMembers.addMethod(method); } } }
@NotNull public Collection<FunctionDescriptor> getTopLevelFunctionDescriptorsByName( @NotNull String name, @NotNull JetSimpleNameExpression expression, @NotNull ResolveSession resolveSession, @NotNull GlobalSearchScope scope) { // name parameter can differ from expression.getReferenceName() when expression contains // completion suffix Name referenceName = expression.getIdentifier() == null ? JetPsiUtil.getConventionName(expression) : Name.identifier(name); if (referenceName == null || referenceName.toString().isEmpty()) { return Collections.emptyList(); } BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression); JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); if (jetScope == null) { return Collections.emptyList(); } Set<FunctionDescriptor> result = Sets.newHashSet(); Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName( referenceName.getName(), project, scope); for (PsiMethod method : topLevelFunctionPrototypes) { FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method); if (functionFQN != null) { JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false)); Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver() .analyseImportReference( importDirective, jetScope, new BindingTraceContext(), resolveSession.getModuleConfiguration()); for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { if (declarationDescriptor instanceof FunctionDescriptor) { result.add((FunctionDescriptor) declarationDescriptor); } } } } Set<FqName> affectedPackages = Sets.newHashSet(); Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(referenceName.getName(), project, scope); for (JetNamedFunction jetNamedFunction : jetNamedFunctions) { PsiFile containingFile = jetNamedFunction.getContainingFile(); if (containingFile instanceof JetFile) { JetFile jetFile = (JetFile) containingFile; String packageName = jetFile.getPackageName(); if (packageName != null) { affectedPackages.add(new FqName(packageName)); } } } for (FqName affectedPackage : affectedPackages) { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(affectedPackage); assert packageDescriptor != null : "There's a function in stub index with invalid package: " + affectedPackage; JetScope memberScope = packageDescriptor.getMemberScope(); result.addAll(memberScope.getFunctions(referenceName)); } return result; }
/** @author Nikolay Krasko */ public class ResolveSessionUtils { // This name is used as a key for the case when something has no name _due to a syntactic error_ // Example: fun (x: Int) = 5 // There's no name for this function in the PSI // The name contains a GUID to avoid clashes, if a clash happens, it's not a big deal: the code // does not compile anyway public static final Name NO_NAME_FOR_LAZY_RESOLVE = Name.identifier("no_name_in_PSI_for_lazy_resolve_3d19d79d_1ba9_4cd0_b7f5_b46aa3cd5d40"); private ResolveSessionUtils() {} @SuppressWarnings("unchecked") private static final BodyResolveContextForLazy EMPTY_CONTEXT = new BodyResolveContextForLazy((Function) Functions.constant(null)); private static class BodyResolveContextForLazy implements BodiesResolveContext { private final Function<JetDeclaration, JetScope> declaringScopes; private BodyResolveContextForLazy(@NotNull Function<JetDeclaration, JetScope> declaringScopes) { this.declaringScopes = declaringScopes; } @Override public Collection<JetFile> getFiles() { return Collections.emptySet(); } @Override public Map<JetClass, MutableClassDescriptor> getClasses() { return Collections.emptyMap(); } @Override public Map<JetObjectDeclaration, MutableClassDescriptor> getObjects() { return Collections.emptyMap(); } @Override public Map<JetProperty, PropertyDescriptor> getProperties() { return Collections.emptyMap(); } @Override public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() { return Collections.emptyMap(); } @Override public Function<JetDeclaration, JetScope> getDeclaringScopes() { return declaringScopes; } @Override public Map<JetScript, ScriptDescriptor> getScripts() { return Collections.emptyMap(); } @Override public Map<JetScript, WritableScope> getScriptScopes() { return Collections.emptyMap(); } @Override public void setTopDownAnalysisParameters(TopDownAnalysisParameters parameters) {} @Override public boolean completeAnalysisNeeded(@NotNull PsiElement element) { return true; } } public static @NotNull BindingContext resolveToExpression( @NotNull final ResolveSession resolveSession, @NotNull JetExpression expression) { final DelegatingBindingTrace trace = new DelegatingBindingTrace( resolveSession.getBindingContext(), "trace to resolve expression", expression); JetFile file = (JetFile) expression.getContainingFile(); @SuppressWarnings("unchecked") PsiElement topmostCandidateForAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes( expression, JetNamedFunction.class, JetClassInitializer.class, JetProperty.class, JetDelegationSpecifierList.class); if (topmostCandidateForAdditionalResolve != null) { if (topmostCandidateForAdditionalResolve instanceof JetNamedFunction) { functionAdditionalResolve( resolveSession, (JetNamedFunction) topmostCandidateForAdditionalResolve, trace, file); } else if (topmostCandidateForAdditionalResolve instanceof JetClassInitializer) { initializerAdditionalResolve( resolveSession, (JetClassInitializer) topmostCandidateForAdditionalResolve, trace, file); } else if (topmostCandidateForAdditionalResolve instanceof JetProperty) { propertyAdditionalResolve( resolveSession, (JetProperty) topmostCandidateForAdditionalResolve, trace, file); } else if (topmostCandidateForAdditionalResolve instanceof JetDelegationSpecifierList) { delegationSpecifierAdditionalResolve( resolveSession, (JetDelegationSpecifierList) topmostCandidateForAdditionalResolve, trace, file); } else { assert false : "Invalid type of the topmost parent"; } return trace.getBindingContext(); } // Setup resolution scope explicitly if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, expression) == null) { JetScope scope = getExpressionMemberScope(resolveSession, expression); if (scope != null) { trace.record(BindingContext.RESOLUTION_SCOPE, expression, scope); } } return trace.getBindingContext(); } private static void delegationSpecifierAdditionalResolve( final ResolveSession resolveSession, final JetDelegationSpecifierList specifier, DelegatingBindingTrace trace, JetFile file) { BodyResolver bodyResolver = createBodyResolverWithEmptyContext(trace, file, resolveSession.getModuleConfiguration()); JetClassOrObject classOrObject = (JetClassOrObject) specifier.getParent(); LazyClassDescriptor descriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject); // Activate resolving of supertypes descriptor.getTypeConstructor().getSupertypes(); bodyResolver.resolveDelegationSpecifierList( classOrObject, descriptor, descriptor.getUnsubstitutedPrimaryConstructor(), descriptor.getScopeForClassHeaderResolution(), descriptor.getScopeForMemberDeclarationResolution()); } private static void propertyAdditionalResolve( final ResolveSession resolveSession, final JetProperty jetProperty, DelegatingBindingTrace trace, JetFile file) { final JetScope propertyResolutionScope = resolveSession .getInjector() .getScopeProvider() .getResolutionScopeForDeclaration(jetProperty); BodyResolveContextForLazy bodyResolveContext = new BodyResolveContextForLazy( new Function<JetDeclaration, JetScope>() { @Override public JetScope apply(JetDeclaration declaration) { assert declaration.getParent() == jetProperty : "Must be called only for property accessors, but called for " + declaration; return propertyResolutionScope; } }); BodyResolver bodyResolver = createBodyResolver( trace, file, bodyResolveContext, resolveSession.getModuleConfiguration()); PropertyDescriptor descriptor = (PropertyDescriptor) resolveSession.resolveToDescriptor(jetProperty); JetExpression propertyInitializer = jetProperty.getInitializer(); if (propertyInitializer != null) { bodyResolver.resolvePropertyInitializer( jetProperty, descriptor, propertyInitializer, propertyResolutionScope); } bodyResolver.resolvePropertyAccessors(jetProperty, descriptor); } private static void functionAdditionalResolve( ResolveSession resolveSession, JetNamedFunction namedFunction, DelegatingBindingTrace trace, JetFile file) { BodyResolver bodyResolver = createBodyResolverWithEmptyContext(trace, file, resolveSession.getModuleConfiguration()); JetScope scope = resolveSession .getInjector() .getScopeProvider() .getResolutionScopeForDeclaration(namedFunction); FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction); bodyResolver.resolveFunctionBody(trace, namedFunction, functionDescriptor, scope); } private static boolean initializerAdditionalResolve( ResolveSession resolveSession, JetClassInitializer classInitializer, DelegatingBindingTrace trace, JetFile file) { BodyResolver bodyResolver = createBodyResolverWithEmptyContext(trace, file, resolveSession.getModuleConfiguration()); JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(classInitializer, JetClassOrObject.class); LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject); bodyResolver.resolveAnonymousInitializers( classOrObject, classOrObjectDescriptor.getUnsubstitutedPrimaryConstructor(), classOrObjectDescriptor.getScopeForPropertyInitializerResolution()); return true; } private static BodyResolver createBodyResolver( DelegatingBindingTrace trace, JetFile file, BodyResolveContextForLazy bodyResolveContext, ModuleConfiguration moduleConfiguration) { TopDownAnalysisParameters parameters = new TopDownAnalysisParameters( Predicates.<PsiFile>alwaysTrue(), false, true, Collections.<AnalyzerScriptParameter>emptyList()); InjectorForBodyResolve bodyResolve = new InjectorForBodyResolve( file.getProject(), parameters, trace, bodyResolveContext, moduleConfiguration); return bodyResolve.getBodyResolver(); } private static BodyResolver createBodyResolverWithEmptyContext( DelegatingBindingTrace trace, JetFile file, ModuleConfiguration moduleConfiguration) { return createBodyResolver(trace, file, EMPTY_CONTEXT, moduleConfiguration); } private static JetScope getExpressionResolutionScope( @NotNull ResolveSession resolveSession, @NotNull JetExpression expression) { ScopeProvider provider = resolveSession.getInjector().getScopeProvider(); JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class); if (parentDeclaration == null) { return provider.getFileScopeWithAllImported((JetFile) expression.getContainingFile()); } return provider.getResolutionScopeForDeclaration(parentDeclaration); } public static JetScope getExpressionMemberScope( @NotNull ResolveSession resolveSession, @NotNull JetExpression expression) { DelegatingBindingTrace trace = new DelegatingBindingTrace( resolveSession.getBindingContext(), "trace to resolve a member scope of expression", expression); if (expression instanceof JetReferenceExpression) { QualifiedExpressionResolver qualifiedExpressionResolver = resolveSession.getInjector().getQualifiedExpressionResolver(); // In some type declaration if (expression.getParent() instanceof JetUserType) { JetUserType qualifier = ((JetUserType) expression.getParent()).getQualifier(); if (qualifier != null) { Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver.lookupDescriptorsForUserType( qualifier, getExpressionResolutionScope(resolveSession, expression), trace); for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof LazyPackageDescriptor) { return ((LazyPackageDescriptor) descriptor).getMemberScope(); } } } } // Inside import if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class, false) != null) { NamespaceDescriptor rootPackage = resolveSession.getPackageDescriptorByFqName(FqName.ROOT); assert rootPackage != null; if (expression.getParent() instanceof JetDotQualifiedExpression) { JetExpression element = ((JetDotQualifiedExpression) expression.getParent()).getReceiverExpression(); String name = ((JetFile) expression.getContainingFile()).getPackageName(); NamespaceDescriptor filePackage = name != null ? resolveSession.getPackageDescriptorByFqName(new FqName(name)) : rootPackage; assert filePackage != null : "File package should be already resolved and be found"; JetScope scope = filePackage.getMemberScope(); Collection<? extends DeclarationDescriptor> descriptors; if (element instanceof JetDotQualifiedExpression) { descriptors = qualifiedExpressionResolver.lookupDescriptorsForQualifiedExpression( (JetDotQualifiedExpression) element, rootPackage.getMemberScope(), scope, trace, false, false); } else { descriptors = qualifiedExpressionResolver.lookupDescriptorsForSimpleNameReference( (JetSimpleNameExpression) element, rootPackage.getMemberScope(), scope, trace, false, false, false); } for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof NamespaceDescriptor) { return ((NamespaceDescriptor) descriptor).getMemberScope(); } } } else { return rootPackage.getMemberScope(); } } // Inside package declaration JetNamespaceHeader namespaceHeader = PsiTreeUtil.getParentOfType(expression, JetNamespaceHeader.class, false); if (namespaceHeader != null) { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName( namespaceHeader.getParentFqName((JetReferenceExpression) expression)); if (packageDescriptor != null) { return packageDescriptor.getMemberScope(); } } } return null; } @NotNull public static Collection<ClassDescriptor> getClassDescriptorsByFqName( @NotNull ResolveSession resolveSession, @NotNull FqName fqName) { return getClassOrObjectDescriptorsByFqName(resolveSession, fqName, false); } @NotNull public static Collection<ClassDescriptor> getClassOrObjectDescriptorsByFqName( @NotNull ResolveSession resolveSession, @NotNull FqName fqName, boolean includeObjectDeclarations) { if (fqName.isRoot()) { return Collections.emptyList(); } Collection<ClassDescriptor> classDescriptors = Lists.newArrayList(); FqName packageFqName = fqName.parent(); while (true) { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(packageFqName); if (packageDescriptor != null) { FqName classInPackagePath = new FqName(QualifiedNamesUtil.tail(packageFqName, fqName)); Collection<ClassDescriptor> descriptors = getClassOrObjectDescriptorsByFqName( packageDescriptor, classInPackagePath, includeObjectDeclarations); classDescriptors.addAll(descriptors); } if (packageFqName.isRoot()) { break; } else { packageFqName = packageFqName.parent(); } } return classDescriptors; } private static Collection<ClassDescriptor> getClassOrObjectDescriptorsByFqName( NamespaceDescriptor packageDescriptor, FqName path, boolean includeObjectDeclarations) { if (path.isRoot()) { return Collections.emptyList(); } Collection<JetScope> scopes = Arrays.asList(packageDescriptor.getMemberScope()); List<Name> names = path.pathSegments(); if (names.size() > 1) { for (Name subName : path.pathSegments().subList(0, names.size() - 1)) { Collection<JetScope> tempScopes = Lists.newArrayList(); for (JetScope scope : scopes) { ClassifierDescriptor classifier = scope.getClassifier(subName); if (classifier instanceof ClassDescriptorBase) { ClassDescriptorBase classDescriptor = (ClassDescriptorBase) classifier; tempScopes.add(classDescriptor.getUnsubstitutedInnerClassesScope()); } } scopes = tempScopes; } } Name shortName = path.shortName(); Collection<ClassDescriptor> resultClassifierDescriptors = Lists.newArrayList(); for (JetScope scope : scopes) { ClassifierDescriptor classifier = scope.getClassifier(shortName); if (classifier instanceof ClassDescriptor) { resultClassifierDescriptors.add((ClassDescriptor) classifier); } if (includeObjectDeclarations) { ClassDescriptor objectDescriptor = scope.getObjectDescriptor(shortName); if (objectDescriptor != null) { resultClassifierDescriptors.add(objectDescriptor); } } } return resultClassifierDescriptors; } @NotNull public static Name safeNameForLazyResolve(@NotNull JetNamed named) { Name name = named.getNameAsName(); return safeNameForLazyResolve(name); } @NotNull public static Name safeNameForLazyResolve(@Nullable Name name) { return name != null ? name : NO_NAME_FOR_LAZY_RESOLVE; } }