1/* 2 * Copyright 2016, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.smalidea.dexlib; 33 34import com.google.common.base.Function; 35import com.google.common.base.Predicate; 36import com.google.common.collect.ImmutableSet; 37import com.google.common.collect.Iterables; 38import com.google.common.collect.Lists; 39import com.intellij.psi.PsiClass; 40import com.intellij.psi.PsiField; 41import com.intellij.psi.PsiMethod; 42import com.intellij.psi.PsiModifierList; 43import org.jf.dexlib2.AccessFlags; 44import org.jf.dexlib2.base.reference.BaseTypeReference; 45import org.jf.dexlib2.iface.Annotation; 46import org.jf.dexlib2.iface.ClassDef; 47import org.jf.dexlib2.iface.Field; 48import org.jf.dexlib2.iface.Method; 49import org.jf.smalidea.util.NameUtils; 50 51import javax.annotation.Nonnull; 52import javax.annotation.Nullable; 53import java.util.Arrays; 54import java.util.List; 55import java.util.Set; 56 57public class SmalideaClassDef extends BaseTypeReference implements ClassDef { 58 private final PsiClass psiClass; 59 60 public SmalideaClassDef(PsiClass psiClass) { 61 this.psiClass = psiClass; 62 } 63 64 @Override public int getAccessFlags() { 65 PsiModifierList modifierList = psiClass.getModifierList(); 66 int flags = 0; 67 68 if (modifierList == null) { 69 return flags; 70 } 71 72 if (modifierList.hasModifierProperty("public")) { 73 flags |= AccessFlags.PUBLIC.getValue(); 74 } 75 76 if (modifierList.hasModifierProperty("final")) { 77 flags |= AccessFlags.FINAL.getValue(); 78 } 79 80 if (modifierList.hasModifierProperty("abstract")) { 81 flags |= AccessFlags.ABSTRACT.getValue(); 82 } 83 84 if (psiClass.isInterface()) { 85 flags |= AccessFlags.INTERFACE.getValue(); 86 } 87 88 if (psiClass.isEnum()) { 89 flags |= AccessFlags.ENUM.getValue(); 90 } 91 92 if (psiClass.isAnnotationType()) { 93 flags |= AccessFlags.ANNOTATION.getValue(); 94 } 95 96 return flags; 97 } 98 99 @Nonnull @Override public String getType() { 100 return NameUtils.javaToSmaliType(psiClass); 101 } 102 103 @Nullable @Override public String getSuperclass() { 104 PsiClass superClass = psiClass.getSuperClass(); 105 if (superClass == null) { 106 return null; 107 } 108 return NameUtils.javaToSmaliType(superClass); 109 } 110 111 @Nonnull @Override public List<String> getInterfaces() { 112 List<String> interfaceList = Lists.newArrayList(); 113 PsiClass[] interfaces = psiClass.getInterfaces(); 114 if (interfaces == null) { 115 return interfaceList; 116 } 117 118 for (PsiClass psiClass: interfaces) { 119 interfaceList.add(NameUtils.javaToSmaliType(psiClass)); 120 } 121 122 return interfaceList; 123 } 124 125 @Nullable @Override public String getSourceFile() { 126 return null; 127 } 128 129 @Nonnull @Override public Set<? extends Annotation> getAnnotations() { 130 return ImmutableSet.of(); 131 } 132 133 @Nonnull @Override public Iterable<? extends Field> getStaticFields() { 134 return Iterables.transform( 135 Iterables.filter(Arrays.asList(psiClass.getFields()), new Predicate<PsiField>() { 136 @Override public boolean apply(PsiField psiField) { 137 PsiModifierList modifierList = psiField.getModifierList(); 138 if (modifierList == null) { 139 return false; 140 } 141 return modifierList.hasModifierProperty("static"); 142 } 143 }), 144 new Function<PsiField, Field>() { 145 @Nullable @Override public Field apply(@Nullable PsiField psiField) { 146 return new SmalideaField(psiField); 147 } 148 }); 149 } 150 151 @Nonnull @Override public Iterable<? extends Field> getInstanceFields() { 152 return Iterables.transform( 153 Iterables.filter(Arrays.asList(psiClass.getFields()), new Predicate<PsiField>() { 154 @Override public boolean apply(PsiField psiField) { 155 PsiModifierList modifierList = psiField.getModifierList(); 156 if (modifierList == null) { 157 return true; 158 } 159 return !modifierList.hasModifierProperty("static"); 160 } 161 }), 162 new Function<PsiField, Field>() { 163 @Nullable @Override public Field apply(@Nullable PsiField psiField) { 164 return new SmalideaField(psiField); 165 } 166 }); 167 } 168 169 @Nonnull @Override public Iterable<? extends Field> getFields() { 170 return Iterables.concat(getStaticFields(), getInstanceFields()); 171 } 172 173 @Nonnull @Override public Iterable<? extends Method> getDirectMethods() { 174 return Iterables.transform( 175 Iterables.filter( 176 Iterables.concat( 177 Arrays.asList(psiClass.getConstructors()), 178 Arrays.asList(psiClass.getMethods())), 179 new Predicate<PsiMethod>() { 180 @Override public boolean apply(PsiMethod psiMethod) { 181 PsiModifierList modifierList = psiMethod.getModifierList(); 182 return modifierList.hasModifierProperty("static") || 183 modifierList.hasModifierProperty("private") || 184 modifierList.hasModifierProperty("constructor"); 185 } 186 }), 187 new Function<PsiMethod, Method>() { 188 @Nullable @Override public Method apply(PsiMethod psiMethod) { 189 return new SmalideaMethod(psiMethod); 190 } 191 }); 192 } 193 194 @Nonnull @Override public Iterable<? extends Method> getVirtualMethods() { 195 return Iterables.transform( 196 Iterables.filter(Arrays.asList(psiClass.getMethods()), new Predicate<PsiMethod>() { 197 @Override public boolean apply(PsiMethod psiMethod) { 198 PsiModifierList modifierList = psiMethod.getModifierList(); 199 return !modifierList.hasModifierProperty("static") && 200 !modifierList.hasModifierProperty("private") && 201 !modifierList.hasModifierProperty("constructor"); 202 } 203 }), 204 new Function<PsiMethod, Method>() { 205 @Nullable @Override public Method apply(PsiMethod psiMethod) { 206 return new SmalideaMethod(psiMethod); 207 } 208 }); 209 } 210 211 @Nonnull @Override public Iterable<? extends Method> getMethods() { 212 return Iterables.concat(getDirectMethods(), getVirtualMethods()); 213 } 214} 215