use of com.android.tools.idea.res.PsiDataBindingResourceItem in project android by JetBrains.
the class DataBindingConverter method toString.
@Nullable
@Override
public String toString(@Nullable final PsiClass psiClass, final ConvertContext context) {
if (psiClass == null) {
return null;
}
final String qualifiedName = psiClass.getName();
// try and replace with import if possible.
final DataBindingInfo bindingInfo = getDataBindingInfo(context);
if (bindingInfo != null) {
int longestPrefix = 0;
PsiDataBindingResourceItem longestImport = null;
for (final PsiDataBindingResourceItem anImport : bindingInfo.getItems(DataBindingResourceType.IMPORT)) {
// Try and find the longest matching import. For inner classes, either the outer or the inner class may be imported.
final String prefix = getLongestPrefix(anImport.getTypeDeclaration(), qualifiedName);
if (prefix.length() > longestPrefix) {
if (qualifiedName.length() == prefix.length()) {
return AndroidLayoutUtil.getAlias(anImport);
}
final char c = qualifiedName.charAt(prefix.length());
if (c == '.') {
longestPrefix = prefix.length();
longestImport = anImport;
}
}
}
if (longestImport != null) {
return AndroidLayoutUtil.getAlias(longestImport) + qualifiedName.substring(longestPrefix);
}
}
if (qualifiedName.startsWith(JAVA_LANG)) {
return qualifiedName.substring(JAVA_LANG.length());
}
return qualifiedName;
}
use of com.android.tools.idea.res.PsiDataBindingResourceItem in project android by JetBrains.
the class DataBindingConverter method getQualifiedType.
/**
* Get the fully qualified name of the class referenced by {@code nameOrAlias}.
* <p/>
* It is not guaranteed that the class will exist. Also, the name returned here uses '.' for inner classes (like import declarations) and
* not '$' as used by JVM.
*
* @param nameOrAlias a fully qualified name, or an alias as declared in an {@code <import>} or an inner class of the alias.
* @param dataBindingInfo for getting the list of {@code <import>} tags.
* @return the fully qualified name. This does not guarantee that the class will exist.
*/
public static String getQualifiedType(@Nullable String nameOrAlias, @Nullable final DataBindingInfo dataBindingInfo) {
if (nameOrAlias == null) {
return null;
}
nameOrAlias = nameOrAlias.replace('$', '.');
if (dataBindingInfo == null) {
return nameOrAlias;
}
final int i = nameOrAlias.indexOf('.');
final String alias = i >= 0 ? nameOrAlias.substring(0, i) : nameOrAlias;
PsiDataBindingResourceItem imp = getImport(alias, dataBindingInfo);
if (imp != null) {
final String type = imp.getTypeDeclaration();
if (type != null) {
return nameOrAlias.equals(alias) ? type : type + nameOrAlias.substring(alias.length());
}
}
return nameOrAlias;
}
use of com.android.tools.idea.res.PsiDataBindingResourceItem in project android by JetBrains.
the class DataBindingConverter method createReferences.
@NotNull
@Override
public PsiReference[] createReferences(final GenericDomValue<PsiClass> value, final PsiElement element, final ConvertContext context) {
assert element instanceof XmlAttributeValue;
final XmlAttributeValue attrValue = (XmlAttributeValue) element;
final String strValue = attrValue.getValue();
final int start = attrValue.getValueTextRange().getStartOffset() - attrValue.getTextRange().getStartOffset();
List<PsiReference> result = new ArrayList<>();
final String[] nameParts = strValue.split("[$.]");
Module module = context.getModule();
if (nameParts.length == 0 || module == null) {
return PsiReference.EMPTY_ARRAY;
}
int offset = start;
// Check if the first namePart is an alias.
DataBindingInfo bindingInfo = getDataBindingInfo(context);
// for iterating over the nameParts.
int idx = 0;
// difference in lengths of the "type" and the "alias". Used in range computation later.
int diff = 0;
String fullType = strValue.replace('$', '.');
if (bindingInfo != null) {
String alias = nameParts[idx];
PsiDataBindingResourceItem anImport = getImport(alias, bindingInfo);
if (anImport != null) {
// Found an import matching the first namePart. Add a reference from this to the type.
idx++;
TextRange range = new TextRange(offset, offset += alias.length());
// Skip the next dot or dollar separator (if any)
offset++;
String type = anImport.getTypeDeclaration();
result.add(new AliasedReference(element, range, type, module));
fullType = type + fullType.substring(alias.length());
diff = type.length() - alias.length();
} else {
// Check java.lang and primitives
if (nameParts.length == 1) {
if (alias.length() > 0) {
if (Character.isLowerCase(alias.charAt(0))) {
final PsiPrimitiveType primitive = PsiJavaParserFacadeImpl.getPrimitiveType(alias);
if (primitive != null) {
result.add(new PsiReferenceBase<PsiElement>(element, true) {
@Nullable
@Override
public PsiElement resolve() {
return myElement;
}
@NotNull
@Override
public Object[] getVariants() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
});
}
} else {
// java.lang
PsiClass aClass = JavaPsiFacade.getInstance(context.getProject()).findClass(JAVA_LANG + alias, GlobalSearchScope.moduleWithLibrariesScope(module));
if (aClass != null) {
final TextRange range = new TextRange(offset, offset += alias.length());
result.add(new ClassReference(element, range, aClass));
}
}
idx++;
}
}
}
}
for (; idx < nameParts.length; idx++, offset++) {
final String packageName = nameParts[idx];
if (packageName.length() > 0) {
final TextRange range = new TextRange(offset, offset += packageName.length());
result.add(new AliasedReference(element, range, fullType.substring(0, diff + offset - start), module));
}
}
return result.toArray(new PsiReference[result.size()]);
}
use of com.android.tools.idea.res.PsiDataBindingResourceItem in project android by JetBrains.
the class LightBindingClass method processDeclarations.
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) {
boolean continueProcessing = super.processDeclarations(processor, state, lastParent, place);
if (!continueProcessing) {
return false;
}
List<PsiDataBindingResourceItem> imports = myInfo.getItems(DataBindingResourceType.IMPORT);
if (imports.isEmpty()) {
return true;
}
final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
if (classHint != null && classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
final NameHint nameHint = processor.getHint(NameHint.KEY);
final String name = nameHint != null ? nameHint.getName(state) : null;
for (PsiDataBindingResourceItem imp : imports) {
String alias = imp.getExtra(SdkConstants.ATTR_ALIAS);
if (alias != null) {
// aliases are pre-resolved in {@linkplain #replaceImportAliases}
continue;
}
String qName = imp.getExtra(SdkConstants.ATTR_TYPE);
if (qName == null) {
continue;
}
if (name != null && !qName.endsWith("." + name)) {
continue;
}
Module module = myInfo.getModule();
if (module == null) {
// this should not really happen but just to be safe
return true;
}
PsiClass aClass = JavaPsiFacade.getInstance(myManager.getProject()).findClass(qName, module.getModuleWithDependenciesAndLibrariesScope(true));
if (aClass != null) {
if (!processor.execute(aClass, state)) {
// found it!
return false;
}
}
}
}
return true;
}
Aggregations