private static void checkNestedStringFormat(JavaContext context, UCallExpression call) { UElement current = call; while (true) { current = LintUtils.skipParentheses(current.getUastParent()); if (current == null || current instanceof UMethod) { // Reached AST root or code block node; String.format not inside Timber.X(..). return; } if (current instanceof UCallExpression) { UCallExpression maybeTimberLogCall = (UCallExpression) current; JavaEvaluator evaluator = context.getEvaluator(); PsiMethod psiMethod = maybeTimberLogCall.resolve(); if (Pattern.matches(TIMBER_TREE_LOG_METHOD_REGEXP, psiMethod.getName()) && evaluator.isMemberInClass(psiMethod, "timber.log.Timber")) { LintFix fix = quickFixIssueFormat(call); context.report(ISSUE_FORMAT, call, context.getLocation(call), "Using 'String#format' inside of 'Timber'", fix); return; } } } }
@Nullable public static PsiType getWritablePropertyType(@Nullable PsiClass containingClass, @Nullable PsiElement declaration) { if (declaration instanceof PsiField) { return getWrappedPropertyType((PsiField) declaration, JavaFxCommonNames.ourWritableMap); } if (declaration instanceof PsiMethod) { final PsiMethod method = (PsiMethod) declaration; if (method.getParameterList().getParametersCount() != 0) { return getSetterArgumentType(method); } final String propertyName = PropertyUtil.getPropertyName(method); final PsiClass psiClass = containingClass != null ? containingClass : method.getContainingClass(); if (propertyName != null && containingClass != null) { final PsiMethod setter = findInstancePropertySetter(psiClass, propertyName); if (setter != null) { final PsiType setterArgumentType = getSetterArgumentType(setter); if (setterArgumentType != null) return setterArgumentType; } } return getGetterReturnType(method); } return null; }
private static boolean hasGetAndSet(@NonNull String getPrefix, @NonNull String setPrefix, @NonNull PsiClass cls, @NonNull PsiField field) { boolean isPublic = field.hasModifierProperty(PsiModifier.PUBLIC); if (isPublic) return true; String fieldName = captureName(field.getName()); String getMethodName = getPrefix + fieldName; String setMethodName = setPrefix + fieldName; PsiMethod[] gets = cls.findMethodsByName(getMethodName, true); PsiMethod[] sets = cls.findMethodsByName(setMethodName, true); boolean hasGet = gets.length > 0; boolean hasSet = sets.length > 0; return hasGet && hasSet; }
@Override public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) { boolean isLayoutInflaterCall = isLayoutInflaterCall(context, node, method); boolean isViewInflateCall = isInViewCall(context, node, method); String name = method.getName(); boolean fromMethod = LAYOUTINFLATER_FROM.equals(name); boolean viewInflateMethod = VIEW_INFLATE.equals(name); if (isLayoutInflaterCall && fromMethod) { context.report(ISSUE_LAYOUTINFLATER, node, context.getLocation(node), "error use system LayoutInflater,should use LayoutInflaterWrapper."); return; } if (viewInflateMethod && isViewInflateCall) { context.report(ISSUE_VIEW_INFLATE, node, context.getLocation(node), "error use View.inflate(),should use LayoutInflaterWrapper.inflate."); return; } }
@Override public void visitMethod(JavaContext context, JavaElementVisitor visitor, PsiMethodCallExpression call, PsiMethod method) { JavaEvaluator evaluator = context.getEvaluator(); if (evaluator.getParameterCount(method) == 0) { PsiMethod parent = PsiTreeUtil.getParentOfType(call, PsiMethod.class); if (parent != null) { if (evaluator.isMemberInClass(method, CLASS_DIRECTOR) && evaluator.isMemberInSubClassOf(parent, CLASS_DIRECTOR_BACK_HANDLER, false)) { context.report(ISSUE, call, context.getLocation(call), "Can't call Stage.handleBack() in Stage.BackHandler.handleBack()"); } else if (evaluator.isMemberInClass(method, CLASS_STAGE) && evaluator.isMemberInSubClassOf(parent, CLASS_STAGE_BACK_HANDLER, false)) { context.report(ISSUE, call, context.getLocation(call), "Can't call Director.handleBack() in Director.BackHandler.handleBack()"); } } } }
private boolean checkMethodSignature(PsiMethod method) { // subscribe() calls that have no return type are custom Observers whose error handling we cannot check if (PsiType.VOID.equals(method.getReturnType())) { return false; } int argCount = method.getParameterList().getParametersCount(); // when more than one argument is given, there is usually one error callback included if (argCount > 1) { return false; } // no arguments, no error handling if (argCount == 0) { return true; } // if we have only one argument, check that it's not a BiConsumer PsiParameter parameter = method.getParameterList().getParameters()[0]; return !"io.reactivex.functions.BiConsumer".equals(parameter.getType().getCanonicalText()); }
@Override public void visitMethod(JavaContext context, JavaElementVisitor visitor, PsiMethodCallExpression call, PsiMethod method) { super.visitMethod(context, visitor, call, method); if (isRxSubscribeableClass(method.getContainingClass()) && !PsiType.VOID.equals(method.getReturnType())) { PsiElement element = LintUtils.skipParentheses(call.getParent()); if (element instanceof PsiExpressionStatement) { String message; if (isRx2(method.getContainingClass())) { message = "No reference to the disposable is kept"; } else { message = "No reference to the subscription is kept"; } context.report(ISSUE, call, context.getLocation(call), message); } } }
@Override public boolean canProcessElement( @NotNull PsiElement elem ) { PsiElement[] element = new PsiElement[]{elem}; List<PsiElement> javaElems = findJavaElements( element ); if( javaElems.isEmpty() ) { return false; } for( PsiElement javaElem : javaElems ) { if( !(javaElem instanceof PsiMethod) && !(javaElem instanceof PsiField) && !(javaElem instanceof PsiClass) ) { return false; } } return true; }
private PsiMethod makePsiMethod( AbstractSrcMethod method, PsiClass psiClass ) { PsiElementFactory elementFactory = JavaPsiFacade.getInstance( psiClass.getProject() ).getElementFactory(); StringBuilder sb = new StringBuilder(); method.render( sb, 0 ); try { return elementFactory.createMethodFromText( sb.toString(), psiClass ); } catch( IncorrectOperationException ioe ) { // the text of the method does not conform to method grammar, probably being edited in an IJ editor, // ignore these since the editor provides error information return null; } }
private PsiElement findExtensionMethodNavigationElement( PsiClass extClass, PsiMethod plantedMethod ) { PsiMethod[] found = extClass.findMethodsByName( plantedMethod.getName(), false ); outer: for( PsiMethod m : found ) { PsiParameter[] extParams = m.getParameterList().getParameters(); PsiParameter[] plantedParams = plantedMethod.getParameterList().getParameters(); if( extParams.length - 1 == plantedParams.length ) { for( int i = 1; i < extParams.length; i++ ) { PsiParameter extParam = extParams[i]; PsiParameter plantedParam = plantedParams[i - 1]; PsiType extErased = TypeConversionUtil.erasure( extParam.getType() ); PsiType plantedErased = TypeConversionUtil.erasure( plantedParam.getType() ); if( !extErased.toString().equals( plantedErased.toString() ) ) { continue outer; } } return m.getNavigationElement(); } } return null; }
public SrcClass makeSrcClass( String fqn, PsiClass psiClass, ManModule module ) { SrcClass srcClass = new SrcClass( fqn, getKind( psiClass ) ) .modifiers( getModifiers( psiClass.getModifierList() ) ); for( PsiTypeParameter typeVar : psiClass.getTypeParameters() ) { srcClass.addTypeVar( new SrcType( makeTypeVar( typeVar ) ) ); } setSuperTypes( srcClass, psiClass ); for( PsiMethod psiMethod : psiClass.getMethods() ) { addMethod( srcClass, psiMethod ); } for( PsiField psiField : psiClass.getFields() ) { addField( srcClass, psiField ); } for( PsiClass psiInnerClass : psiClass.getInnerClasses() ) { addInnerClass( srcClass, psiInnerClass, module ); } return srcClass; }
void check(@NonNull PsiMethod method) { if (mClass != null && !mClassFields.isEmpty()) { // メソッド引数に boolean のパラメータがある場合のみ対象とする Map<String, PsiParameter> parameters = new HashMap<>(); PsiParameter[] params = method.getParameterList().getParameters(); for (PsiParameter param : params) { if (param.getType() != PsiType.BOOLEAN) continue; parameters.put(param.getName(), param); } if (parameters.isEmpty()) return; mMethod = method; mFlagMethodParameters.clear(); mFlagMethodParameters.putAll(parameters); mFlagLogic = null; } }
void check(@NonNull PsiMethod method) { if (mClass == null) return; Debug.checkedMethod(mClass, method); if (!mUnusedMethods.remove(method)) { // クラス内のインナークラスや匿名クラスに無名クラスのメソッドは、対象としていません。 return; } if (method.isConstructor()) return; // メソッドを関数とフィールド変数変更メソッドに分離 WriteFieldGroupMethod writeFieldGroup = new WriteFieldGroupMethod(method, mClassFields); if (writeFieldGroup.hasWriteFields()) { mWriteFieldGroupMethods.add(writeFieldGroup); } else { mFunctions.add(writeFieldGroup); } if (mUnusedMethods.isEmpty()) { Debug.methodTypes(mClass, mWriteFieldGroupMethods, mFunctions); // フィールド変数変更メソッドのグループ分け開始 parse(); clean(); } }
private static boolean applyTestMethodConfiguration(@NotNull ExternalSystemRunConfiguration configuration, @NotNull ConfigurationContext context, @NotNull PsiMethod psiMethod, @NotNull PsiClass... containingClasses) { if (!StringUtil.equals( context.getModule().getOptionValue(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY), GradleConstants.SYSTEM_ID.toString())) { return false; } configuration.getSettings().setExternalProjectPath(context.getModule().getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY)); configuration.getSettings().setTaskNames(TASKS_TO_RUN); StringBuilder buf = new StringBuilder(); for (PsiClass aClass : containingClasses) { buf.append(creatTestFilter(aClass, psiMethod)); } configuration.getSettings().setScriptParameters(buf.toString().trim()); configuration.setName(psiMethod.getName()); return true; }
@Override public void visitMethod(@NotNull PsiMethod method) { //no call to super, so we don't drill into anonymous classes if (method.isConstructor()) { return; } if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { return; } if (method.getNameIdentifier() == null) { return; } final PsiMethod[] superMethods = method.findSuperMethods(); for (final PsiMethod superMethod : superMethods) { if (superMethod.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { registerMethodError(method); return; } } }
@Override protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { clear(); PropertyTable.updateRenderer(this, selected); if (value == StringsComboEditor.UNSET) { append(StringsComboEditor.UNSET); } else if (value instanceof EventHandlerEditor.PsiMethodWrapper) { PsiMethod method = ((EventHandlerEditor.PsiMethodWrapper)value).getMethod(); setIcon(method.getIcon(Iconable.ICON_FLAG_VISIBILITY)); append(method.getName()); PsiClass psiClass = method.getContainingClass(); if (psiClass != null) { append(" (" + psiClass.getQualifiedName() + ")"); } } }
static PsiMethod isTheLastClassRef(PsiElement element, PsiMethod member) { final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); if ( containingMethod != null && !containingMethod.hasModifierProperty(PsiModifier.STATIC) && !containingMethod.isConstructor() && containingMethod.findDeepestSuperMethods().length == 0 && !containingMethod.equals(member)) { final PsiClass containingClass = containingMethod.getContainingClass(); if (containingClass != null) { final PsiClass gContainingClass = containingClass.getContainingClass(); if (gContainingClass == null || gContainingClass.hasModifierProperty(PsiModifier.STATIC)) { final InternalUsageInfo[] refsInMember = MakeStaticUtil.findClassRefsInMember(containingMethod, true); for (InternalUsageInfo info : refsInMember) { final PsiElement referencedElement = info.getReferencedElement(); if (!member.equals(referencedElement) && !containingMethod.equals(referencedElement)) { return null; } } return containingMethod; } } } return null; }
public AutomaticParametersRenamer(PsiParameter param, String newParamName) { final PsiElement scope = param.getDeclarationScope(); if (scope instanceof PsiMethod) { final PsiMethod method = (PsiMethod)scope; final int parameterIndex = method.getParameterList().getParameterIndex(param); if (parameterIndex < 0) return; for (PsiMethod overrider : OverridingMethodsSearch.search(method)) { final PsiParameter[] parameters = overrider.getParameterList().getParameters(); if (parameterIndex >= parameters.length) continue; final PsiParameter inheritedParam = parameters[parameterIndex]; if (!Comparing.strEqual(inheritedParam.getName(), newParamName)) { myElements.add(inheritedParam); suggestAllNames(inheritedParam.getName(), newParamName); } } } }
/** * Get a test method which is considered selected in the given context, belonging to a * non-abstract class. The context location may be the method itself, or anywhere inside the * method. * * @param context The context to search for a test method in. * @return A test method, or null if none are found. */ @Nullable public static PsiMethod getIndirectlySelectedMethod(@NotNull ConfigurationContext context) { final Location<?> contextLocation = context.getLocation(); if (contextLocation == null) { return null; } Iterator<Location<PsiMethod>> locationIterator = contextLocation.getAncestors(PsiMethod.class, false); while (locationIterator.hasNext()) { Location<PsiMethod> methodLocation = locationIterator.next(); if (JUnitUtil.isTestMethod(methodLocation)) { return methodLocation.getPsiElement(); } } return null; }
/** * checks for the case string.isEmpty() ? something_else : string */ private static boolean checkForStringIsEmpty(GrExpression condition, GrExpression elseBranch) { if (condition instanceof GrMethodCall) condition = ((GrMethodCall)condition).getInvokedExpression(); if (!(condition instanceof GrReferenceExpression)) return false; final GrExpression qualifier = ((GrReferenceExpression)condition).getQualifier(); if (qualifier == null) return false; if (!PsiEquivalenceUtil.areElementsEquivalent(qualifier, elseBranch)) return false; final PsiType type = qualifier.getType(); if (type == null) return false; if (!type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) return false; final PsiElement resolved = ((GrReferenceExpression)condition).resolve(); return resolved instanceof PsiMethod && "isEmpty".equals(((PsiMethod)resolved).getName()) && ((PsiMethod)resolved).getParameterList().getParametersCount() == 0; }
private void doAutomaticRenameMethod(final String className, final String methodSignature, final String newName) throws Exception { doTest((rootDir, rootAfter) -> { final JavaPsiFacade manager = getJavaFacade(); final PsiClass aClass = manager.findClass(className, GlobalSearchScope.moduleScope(myModule)); assertNotNull(aClass); final PsiMethod methodBySignature = aClass.findMethodBySignature(manager.getElementFactory().createMethodFromText( methodSignature + "{}", null), false); assertNotNull(methodBySignature); final RenameProcessor processor = new RenameProcessor(myProject, methodBySignature, newName, false, false); for (AutomaticRenamerFactory factory : Extensions.getExtensions(AutomaticRenamerFactory.EP_NAME)) { processor.addRenamerFactory(factory); } processor.run(); PsiDocumentManager.getInstance(myProject).commitAllDocuments(); FileDocumentManager.getInstance().saveAllDocuments(); }); }
@Override public void visitMethod(@NotNull PsiMethod method) { // note: no call to super if (method.getNameIdentifier() == null) { return; } final CouplingVisitor visitor = new CouplingVisitor( method, m_includeJavaClasses, m_includeLibraryClasses); method.accept(visitor); final int coupling = visitor.getNumDependencies(); if (coupling <= getLimit()) { return; } registerMethodError(method, Integer.valueOf(coupling)); }
@Override public void visitMethod(@NotNull PsiMethod method) { //note: no call to super @NonNls final String methodName = method.getName(); if (!"suite".equals(methodName)) { return; } final PsiClass aClass = method.getContainingClass(); if (aClass == null) { return; } if (!InheritanceUtil.isInheritor(aClass, "junit.framework.TestCase")) { return; } final PsiParameterList parameterList = method.getParameterList(); if (parameterList.getParametersCount() != 0) { return; } if (method.hasModifierProperty(PsiModifier.STATIC)) { return; } registerMethodError(method); }
private static boolean isSetSecurityManager( PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); @NonNls final String methodName = methodExpression.getReferenceName(); if (!"setSecurityManager".equals(methodName)) { return false; } final PsiMethod method = expression.resolveMethod(); if (method == null) { return false; } final PsiClass aClass = method.getContainingClass(); if (aClass == null) { return false; } final String className = aClass.getQualifiedName(); if (className == null) { return false; } return "java.lang.System".equals(className); }
@Override public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes) throws CantRunException { final TestData data = myConfig.getPersistantData(); //for a group, we include all classes final SourceScope sourceScope = data.getScope().getSourceScope(myConfig); final TestClassFilter classFilter = new TestClassFilter(sourceScope != null ? sourceScope.getGlobalSearchScope() : GlobalSearchScope.allScope(myConfig.getProject()), myConfig.getProject(), true, true); PsiClass[] testClasses = TestNGUtil.getAllTestClasses(classFilter, false); if (testClasses != null) { for (PsiClass c : testClasses) { classes.put(c, new LinkedHashMap<PsiMethod, List<String>>()); } } }
@Test public void testMethodLocationResolves() { PsiFile javaFile = workspace.createPsiFile( new WorkspacePath("java/com/google/lib/JavaClass.java"), "package com.google.lib;", "import org.junit.Test;", "import org.junit.runner.RunWith;", "import org.junit.runners.JUnit4;", "@RunWith(JUnit4.class)", "public class JavaClass {", " @Test", " public void testMethod() {}", "}"); PsiClass javaClass = ((PsiClassOwner) javaFile).getClasses()[0]; PsiMethod method = javaClass.findMethodsByName("testMethod", false)[0]; assertThat(method).isNotNull(); String url = handler.testLocationUrl( null, null, "JavaClass-testMethod", "com.google.test.AndroidTestBase"); Location<?> location = getLocation(url); assertThat(location.getPsiElement()).isEqualTo(method); }
private static Collection<PsiReference> findPropertyReferences(final Property pproperty, final Module module) { final Collection<PsiReference> references = Collections.synchronizedList(new ArrayList<PsiReference>()); ProgressManager.getInstance().runProcessWithProgressSynchronously( new Runnable() { public void run() { ReferencesSearch.search(pproperty).forEach(new Processor<PsiReference>() { public boolean process(final PsiReference psiReference) { PsiMethod method = PsiTreeUtil.getParentOfType(psiReference.getElement(), PsiMethod.class); if (method == null || !AsmCodeGenerator.SETUP_METHOD_NAME.equals(method.getName())) { references.add(psiReference); } return true; } }); } }, UIDesignerBundle.message("edit.text.searching.references"), false, module.getProject() ); return references; }
private static boolean isUtilityMethod(@NotNull PsiMethod method, @NotNull PsiClass psiClass, @NotNull TestFramework framework) { if (method == framework.findSetUpMethod(psiClass) || method == framework.findTearDownMethod(psiClass)) { return true; } // JUnit3 if (framework.getClass().getName().contains("JUnit3")) { return !method.getName().startsWith("test"); } // JUnit4 else if (framework.getClass().getName().contains("JUnit4")) { return !AnnotationUtil.isAnnotated(method, "org.junit.Test", false); } return false; }
@Override public void visitMethod(JavaContext context, UCallExpression call, PsiMethod method) { String methodName = call.getMethodName(); JavaEvaluator evaluator = context.getEvaluator(); if ("format".equals(methodName) && evaluator.isMemberInClass(method, "java.lang.String")) { checkNestedStringFormat(context, call); return; } // As of API 24, Log tags are no longer limited to 23 chars. if ("tag".equals(methodName) && evaluator.isMemberInClass(method, "timber.log.Timber") && context.getMainProject().getMinSdk() <= 23) { checkTagLength(context, call); return; } if (evaluator.isMemberInClass(method, "android.util.Log")) { LintFix fix = quickFixIssueLog(call); context.report(ISSUE_LOG, call, context.getLocation(call), "Using 'Log' instead of 'Timber'", fix); return; } // Handles Timber.X(..) and Timber.tag(..).X(..) where X in (v|d|i|w|e|wtf). if (evaluator.isMemberInClass(method, "timber.log.Timber") // || evaluator.isMemberInClass(method, "timber.log.Timber.Tree")) { checkMethodArguments(context, call); checkFormatArguments(context, call); checkExceptionLogging(context, call); } }
private static Class<?> getType(UExpression expression) { if (expression == null) { return null; } if (expression instanceof PsiMethodCallExpression) { PsiMethodCallExpression call = (PsiMethodCallExpression) expression; PsiMethod method = call.resolveMethod(); if (method == null) { return null; } String methodName = method.getName(); if (methodName.equals(GET_STRING_METHOD)) { return String.class; } } else if (expression instanceof PsiLiteralExpression) { PsiLiteralExpression literalExpression = (PsiLiteralExpression) expression; PsiType expressionType = literalExpression.getType(); if (LintUtils.isString(expressionType)) { return String.class; } else if (expressionType == PsiType.INT) { return Integer.TYPE; } else if (expressionType == PsiType.FLOAT) { return Float.TYPE; } else if (expressionType == PsiType.CHAR) { return Character.TYPE; } else if (expressionType == PsiType.BOOLEAN) { return Boolean.TYPE; } else if (expressionType == PsiType.NULL) { return Object.class; } } PsiType type = expression.getExpressionType(); if (type != null) { Class<?> typeClass = getTypeClass(type); return typeClass != null ? typeClass : Object.class; } return null; }
private static boolean isCallFromMethodInSubclassOf(JavaContext context, UCallExpression call, String methodName, String className) { JavaEvaluator evaluator = context.getEvaluator(); PsiMethod method = call.resolve(); return method != null // && methodName.equals(call.getMethodName()) // && evaluator.isMemberInSubClassOf(method, className, false); }
@NotNull public static Optional<PsiField> findSettablePsiField(@NotNull PsiClass clazz, @Nullable String propertyName) { PsiMethod propertySetter = PropertyUtil.findPropertySetter(clazz, propertyName, false, true); return null == propertySetter ? Optional.empty() : Optional.ofNullable(PropertyUtil.findPropertyFieldByMember(propertySetter)); }
@Nullable private static PsiType getSetterArgumentType(@NotNull PsiMethod method) { return CachedValuesManager.getCachedValue(method, () -> { final PsiParameter[] parameters = method.getParameterList().getParameters(); if (!method.hasModifierProperty(STATIC) && parameters.length == 1) { final PsiType argumentType = eraseFreeTypeParameters(parameters[0].getType(), method); return CachedValueProvider.Result.create(argumentType, JAVA_STRUCTURE_MODIFICATION_COUNT); } return CachedValueProvider.Result.create(null, JAVA_STRUCTURE_MODIFICATION_COUNT); }); }
@Nullable public static PsiMethod findInstancePropertySetter(@NotNull PsiClass psiClass, @Nullable String propertyName) { if (StringUtil.isEmpty(propertyName)) return null; final String suggestedSetterName = PropertyUtil.suggestSetterName(propertyName); final PsiMethod[] setters = psiClass.findMethodsByName(suggestedSetterName, true); for (PsiMethod setter : setters) { if (setter.hasModifierProperty(PUBLIC) && !setter.hasModifierProperty(STATIC) && isSimplePropertySetter(setter)) { return setter; } } return null; }
@Override public void checkClass(JavaContext context, PsiClass node) { super.checkClass(context, node); PsiMethod[] methods = node.getAllMethods(); mMethods.clear(); for (PsiMethod method : methods) { visitMethod(context, method); } afterCheckClass(context); }
public void visitMethod(JavaContext context, PsiMethod method) { boolean isPublicMethod = method.hasModifierProperty(PsiModifier.PUBLIC); if (!isPublicMethod) return; JavaEvaluator evaluator = context.getEvaluator(); if (evaluator == null) return; PsiParameterList parameterList = method.getParameterList(); PsiParameter[] psiParameters = parameterList.getParameters(); boolean hasBeanParameter = false; for (PsiParameter p : psiParameters) { PsiType type = p.getType(); if (!(type instanceof PsiClassType)) continue; PsiClassType classType = (PsiClassType) type; PsiClass psiCls = classType.resolve(); if (psiCls == null) continue; hasBeanParameter = Utils.isCustomBean(context, psiCls); if (hasBeanParameter) break; } if (hasBeanParameter) { mMethods.add(method); } }
public void afterCheckClass(Context context) { if (mMethods.size() == 0) return; JavaContext javaContext = (JavaContext) context; JavaEvaluator evaluator = javaContext.getEvaluator(); if (evaluator == null) return; StringBuilder sb = new StringBuilder(); boolean methodInDataAdapter = false; for (PsiMethod method : mMethods) { PsiClass pc = method.getContainingClass(); boolean isSubclass = evaluator.implementsInterface(pc, CLASS_DATA_ADAPTER, false); methodInDataAdapter = methodInDataAdapter || isSubclass; if (!isSubclass) { sb.append(method.getName()) .append(","); } } if (!methodInDataAdapter) { context.report(ISSUE_VIEW_GROUP, Location.create(context.file), "the Custom ViewGroup with data bind should extend DataAdapter,method names:" + sb.toString()); } }
@Override public void visitNewExpression(PsiNewExpression expression) { super.visitNewExpression(expression); PsiMethod constructor = expression.resolveConstructor(); if (constructor == null) return; JavaEvaluator evaluator = mContext.getEvaluator(); PsiClass cls = constructor.getContainingClass(); boolean isView = evaluator.extendsClass(cls, CLASS_VIEW, true); if (!isView) return; Location location = this.mContext.getLocation(expression); PsiElement psiElement = expression.getParent(); //创建的变量没有赋值给本地变量,无法指定注解 if (!(psiElement instanceof PsiLocalVariable)) { this.mContext.report(DynamicNewViewDetector.ISSUE, expression, location, "检测到动态创建view操作,new 操作的结果需要赋值给本地变量"); return; } PsiLocalVariable localVariable = (PsiLocalVariable) psiElement; PsiModifierList modifierList = localVariable.getModifierList(); if (modifierList == null) { this.mContext.report(DynamicNewViewDetector.ISSUE, expression, location, "检测到动态创建view操作,确认是否为view指定了唯一标识"); return; } PsiAnnotation[] annotations = modifierList.getAnnotations(); for (PsiAnnotation annotation : annotations) { String fullName = annotation.getQualifiedName(); if (IDENTIFIER_ANNOTATION.equals(fullName)) { return; } } this.mContext.report(DynamicNewViewDetector.ISSUE, expression, location, "检测到动态创建view操作,确认是否为view指定了唯一标识"); }
@Override public void checkClass(JavaContext context, PsiClass declaration) { final JavaEvaluator evaluator = context.getEvaluator(); if (evaluator.isAbstract(declaration)) { return; } if (!evaluator.isPublic(declaration)) { context.report(ISSUE, declaration, context.getLocation(declaration), "Non-abstract Scene class must be public"); return; } if (declaration.getContainingClass() != null && !evaluator.isStatic(declaration)) { context.report(ISSUE, declaration, context.getLocation(declaration), "Inner Scene class must be static"); return; } PsiMethod[] constructors = declaration.getConstructors(); // No constructor means it has default constructor boolean hasNoParametersConstructor = constructors.length == 0; if (!hasNoParametersConstructor) { // Find no-parameter constructor for (PsiMethod constructor : constructors) { if (evaluator.isPublic(constructor)) { PsiParameter[] parameters = constructor.getParameterList().getParameters(); if (parameters.length == 0) { hasNoParametersConstructor = true; break; } } } } if (!hasNoParametersConstructor) { context.report(ISSUE, declaration, context.getLocation(declaration), "Scene class must have a no-parameter constructor"); } }
@Nullable @Override public ProblemDescriptor[] checkMethod(PsiMethod method, InspectionManager manager, boolean isOnTheFly) { if (isNonPrivateMethod(method)) { List<ProblemDescriptor> problemDescriptors = new ArrayList<>(); List<MethodSignatureBackedByPsiMethod> superMethodSignatures = superMethods(method); PsiParameter[] parameters = method.getParameterList().getParameters(); checkMethodParams(manager, problemDescriptors, superMethodSignatures, parameters); checkMethodReturnType(method, manager, problemDescriptors); return problemDescriptors.isEmpty() ? null : problemDescriptors.toArray(new ProblemDescriptor[problemDescriptors.size()]); } return null; }