001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.jet.lang.resolve.java.scope; 018 019import com.google.common.collect.Lists; 020import com.google.common.collect.Maps; 021import com.google.common.collect.Sets; 022import com.intellij.openapi.progress.ProgressIndicatorProvider; 023import com.intellij.openapi.util.Condition; 024import com.intellij.psi.PsiElement; 025import com.intellij.util.containers.ContainerUtil; 026import org.jetbrains.annotations.NotNull; 027import org.jetbrains.annotations.Nullable; 028import org.jetbrains.jet.lang.descriptors.*; 029import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; 030import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; 031import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider; 032import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers; 033import org.jetbrains.jet.lang.resolve.java.provider.PackagePsiDeclarationProvider; 034import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider; 035import org.jetbrains.jet.lang.resolve.name.Name; 036import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl; 037 038import java.util.*; 039 040public abstract class JavaBaseScope extends JetScopeImpl { 041 042 @NotNull 043 protected final JavaSemanticServices semanticServices; 044 @NotNull 045 protected final PsiDeclarationProvider declarationProvider; 046 @NotNull 047 private final Map<Name, Set<FunctionDescriptor>> functionDescriptors = Maps.newHashMap(); 048 @NotNull 049 private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = Maps.newHashMap(); 050 @Nullable 051 private Collection<DeclarationDescriptor> allDescriptors = null; 052 @Nullable 053 private Set<ClassDescriptor> objectDescriptors = null; 054 @NotNull 055 protected final ClassOrNamespaceDescriptor descriptor; 056 057 private Collection<ClassDescriptor> innerClasses = null; 058 059 060 protected JavaBaseScope( 061 @NotNull ClassOrNamespaceDescriptor descriptor, 062 @NotNull JavaSemanticServices semanticServices, 063 @NotNull PsiDeclarationProvider declarationProvider 064 ) { 065 this.semanticServices = semanticServices; 066 this.declarationProvider = declarationProvider; 067 this.descriptor = descriptor; 068 } 069 070 @NotNull 071 @Override 072 public DeclarationDescriptor getContainingDeclaration() { 073 return descriptor; 074 } 075 076 @NotNull 077 @Override 078 public Collection<VariableDescriptor> getProperties(@NotNull Name name) { 079 Set<VariableDescriptor> cached = propertyDescriptors.get(name); 080 if (cached != null) return cached; 081 082 if (allDescriptorsComputed()) { 083 return Collections.emptySet(); 084 } 085 086 Set<VariableDescriptor> computedDescriptors = computePropertyDescriptors(name); 087 propertyDescriptors.put(name, computedDescriptors); 088 return computedDescriptors; 089 } 090 091 @NotNull 092 private Set<VariableDescriptor> computePropertyDescriptors(@NotNull Name name) { 093 return getResolver().resolveFieldGroupByName(name, declarationProvider, descriptor); 094 } 095 096 @NotNull 097 @Override 098 public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) { 099 Set<FunctionDescriptor> cached = functionDescriptors.get(name); 100 if (cached != null) return cached; 101 102 if (allDescriptorsComputed()) { 103 return Collections.emptySet(); 104 } 105 106 Set<FunctionDescriptor> computedDescriptors = computeFunctionDescriptor(name); 107 functionDescriptors.put(name, computedDescriptors); 108 return computedDescriptors; 109 } 110 111 @NotNull 112 protected abstract Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name); 113 114 @NotNull 115 @Override 116 public Collection<DeclarationDescriptor> getAllDescriptors() { 117 if (allDescriptorsComputed()) { 118 return allDescriptors; 119 } 120 121 allDescriptors = computeAllDescriptors(); 122 123 return allDescriptors; 124 } 125 126 private boolean allDescriptorsComputed() { 127 return allDescriptors != null; 128 } 129 130 @NotNull 131 protected Collection<DeclarationDescriptor> computeAllDescriptors() { 132 Collection<DeclarationDescriptor> result = Sets.newHashSet(); 133 result.addAll(computeFieldAndFunctionDescriptors()); 134 result.addAll(filterObjects(getInnerClasses(), false)); 135 return result; 136 } 137 138 @NotNull 139 @Override 140 public Set<ClassDescriptor> getObjectDescriptors() { 141 if (objectDescriptors == null) { 142 objectDescriptors = new HashSet<ClassDescriptor>(filterObjects(getInnerClasses(), true)); 143 } 144 return objectDescriptors; 145 } 146 147 @NotNull 148 protected abstract Collection<ClassDescriptor> computeInnerClasses(); 149 150 @NotNull 151 private Collection<DeclarationDescriptor> computeFieldAndFunctionDescriptors() { 152 Collection<DeclarationDescriptor> result = Lists.newArrayList(); 153 for (NamedMembers members : declarationProvider.getMembersCache().allMembers()) { 154 Name name = members.getName(); 155 ProgressIndicatorProvider.checkCanceled(); 156 result.addAll(getFunctions(name)); 157 ProgressIndicatorProvider.checkCanceled(); 158 result.addAll(getProperties(name)); 159 } 160 return result; 161 } 162 163 @NotNull 164 protected JavaDescriptorResolver getResolver() { 165 return semanticServices.getDescriptorResolver(); 166 } 167 168 //TODO: remove this method 169 @NotNull 170 public PsiElement getPsiElement() { 171 if (declarationProvider instanceof ClassPsiDeclarationProvider) { 172 return ((ClassPsiDeclarationProvider) declarationProvider).getPsiClass(); 173 } 174 if (declarationProvider instanceof PackagePsiDeclarationProvider) { 175 return ((PackagePsiDeclarationProvider) declarationProvider).getPsiPackage(); 176 } 177 throw new IllegalStateException(); 178 } 179 180 @NotNull 181 protected Collection<ClassDescriptor> getInnerClasses() { 182 if (innerClasses == null) { 183 innerClasses = computeInnerClasses(); 184 } 185 return innerClasses; 186 } 187 188 private static <T extends ClassDescriptor> Collection<T> filterObjects(Collection<T> classes, final boolean objects) { 189 return ContainerUtil.filter(classes, new Condition<T>() { 190 @Override 191 public boolean value(T classDescriptor) { 192 return classDescriptor.getKind().isObject() == objects; 193 } 194 }); 195 } 196}