blob: a618e7234ffb865612e02903fa6892a4d6f2c79c [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.databinding;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiField;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class BrShortNamesCache extends PsiShortNamesCache {
private final DataBindingProjectComponent myComponent;
private CachedValue<String[]> myAllFieldNamesCache;
private static final String[] BR_CLASS_NAME_LIST = new String[]{DataBindingUtil.BR};
public BrShortNamesCache(DataBindingProjectComponent dataBindingProjectComponent) {
myComponent = dataBindingProjectComponent;
myAllFieldNamesCache = CachedValuesManager.getManager(myComponent.getProject()).createCachedValue(new CachedValueProvider<String[]>() {
@Nullable
@Override
public Result<String[]> compute() {
AndroidFacet[] facets = myComponent.getDataBindingEnabledFacets();
String[] result;
if (facets.length == 0) {
result = ArrayUtil.EMPTY_STRING_ARRAY;
} else {
Set<String> allFields = Sets.newHashSet();
for (AndroidFacet facet : facets) {
DataBindingUtil.LightBrClass brClass = DataBindingUtil.getOrCreateBrClassFor(facet);
Collections.addAll(allFields, brClass.getAllFieldNames());
}
result = ArrayUtil.toStringArray(allFields);
}
return Result.create(result, myComponent);
}
}, false);
}
private boolean isMyScope(GlobalSearchScope scope) {
if( !myComponent.hasAnyDataBindingEnabledFacet()) {
return false;
}
if (scope.getProject() == null) {
return false;
}
return myComponent.getProject().equals(scope.getProject());
}
@NotNull
@Override
public PsiClass[] getClassesByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope) {
if (!isMyScope(scope)) {
return PsiClass.EMPTY_ARRAY;
}
if (!DataBindingUtil.BR.equals(name)) {
return PsiClass.EMPTY_ARRAY;
}
AndroidFacet[] facets = myComponent.getDataBindingEnabledFacets();
return filterByScope(facets, scope);
}
@NotNull
@Override
public String[] getAllClassNames() {
if (!myComponent.hasAnyDataBindingEnabledFacet()) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
return BR_CLASS_NAME_LIST;
}
@Override
public void getAllClassNames(@NotNull HashSet<String> dest) {
if (!myComponent.hasAnyDataBindingEnabledFacet()) {
return;
}
dest.add(DataBindingUtil.BR);
}
@NotNull
@Override
public PsiMethod[] getMethodsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope) {
return PsiMethod.EMPTY_ARRAY;
}
@NotNull
@Override
public PsiMethod[] getMethodsByNameIfNotMoreThan(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope, int maxCount) {
return PsiMethod.EMPTY_ARRAY;
}
@NotNull
@Override
public PsiField[] getFieldsByNameIfNotMoreThan(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope, int maxCount) {
PsiField[] fields = getFieldsByName(name, scope);
if (fields.length > maxCount) {
return PsiField.EMPTY_ARRAY;
}
return fields;
}
@Override
public boolean processMethodsWithName(@NonNls @NotNull String name,
@NotNull GlobalSearchScope scope,
@NotNull Processor<PsiMethod> processor) {
return true;
}
@NotNull
@Override
public String[] getAllMethodNames() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
@Override
public void getAllMethodNames(@NotNull HashSet<String> set) {
}
@NotNull
@Override
public PsiField[] getFieldsByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope) {
if (!isMyScope(scope)) {
return PsiField.EMPTY_ARRAY;
}
PsiClass[] psiClasses = filterByScope(myComponent.getDataBindingEnabledFacets(), scope);
if (psiClasses.length == 0) {
return PsiField.EMPTY_ARRAY;
}
List<PsiField> result = Lists.newArrayList();
for (PsiClass psiClass : psiClasses) {
PsiField field = psiClass.findFieldByName(name, false);
if (field != null) {
result.add(field);
}
}
return result.toArray(new PsiField[result.size()]);
}
@NotNull
@Override
public String[] getAllFieldNames() {
if (!myComponent.hasAnyDataBindingEnabledFacet()) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
return myAllFieldNamesCache.getValue();
}
@Override
public void getAllFieldNames(@NotNull HashSet<String> set) {
Collections.addAll(set, getAllFieldNames());
}
private static PsiClass[] filterByScope(AndroidFacet[] facets, @NotNull GlobalSearchScope scope) {
if (facets == null || facets.length == 0) {
return PsiClass.EMPTY_ARRAY;
}
List<PsiClass> selected = Lists.newArrayList();
for (AndroidFacet facet : facets) {
if (scope.isSearchInModuleContent(facet.getModule())) {
selected.add(DataBindingUtil.getOrCreateBrClassFor(facet));
}
}
if (selected.size() == 0) {
return PsiClass.EMPTY_ARRAY;
}
return selected.toArray(new PsiClass[selected.size()]);
}
}