void apply()

in buildSrc/src/main/groovy/CheckApiChangesPlugin.groovy [19:160]


    void apply(Project project) {
        project.extensions.create("checkApiChanges", CheckApiChangesExtension)

        project.configurations {
            checkApiChangesFrom
            checkApiChangesTo
        }

        project.afterEvaluate {
            project.checkApiChanges.from.each {
                project.dependencies.checkApiChangesFrom(it) {
                    transitive = false
                    force = true
                }
            }

            project.checkApiChanges.to.findAll { it instanceof String }.each {
                project.dependencies.checkApiChangesTo(it) {
                    transitive = false
                    force = true
                }
            }
        }

        project.task('checkForApiChanges', dependsOn: 'jar') {
            doLast {
                Map<ClassMethod, Change> changedClassMethods = new TreeMap<>()

                def fromUrls = project.configurations.checkApiChangesFrom*.toURI()*.toURL()
                println "fromUrls = ${fromUrls*.toString()*.replaceAll("^.*/", "")}"

                def jarUrls = project.checkApiChanges.to
                        .findAll { it instanceof Project }
                        .collect { it.jar.archivePath.toURL() }
                def toUrls = jarUrls + project.configurations.checkApiChangesTo*.toURI()*.toURL()
                println "toUrls = ${toUrls*.toString()*.replaceAll("^.*/", "")}"

                Analysis prev = new Analysis(fromUrls)
                Analysis cur = new Analysis(toUrls)

                Set<String> allMethods = new TreeSet<>(prev.classMethods.keySet())
                allMethods.addAll(cur.classMethods.keySet())

                Set<ClassMethod> deprecatedNotRemoved = new TreeSet<>()
                Set<ClassMethod> newlyDeprecated = new TreeSet<>()

                for (String classMethodName : allMethods) {
                    ClassMethod prevClassMethod = prev.classMethods.get(classMethodName)
                    ClassMethod curClassMethod = cur.classMethods.get(classMethodName)

                    if (prevClassMethod == null) {
                        // added
                        if (curClassMethod.visible) {
                            changedClassMethods.put(curClassMethod, Change.ADDED)
                        }
                    } else if (curClassMethod == null) {
                        def theClass = prevClassMethod.classNode.name.replace('/', '.')
                        def methodDesc = prevClassMethod.methodDesc
                        while (curClassMethod == null && cur.parents[theClass] != null) {
                            theClass = cur.parents[theClass]
                            def parentMethodName = "${theClass}#${methodDesc}"
                            curClassMethod = cur.classMethods[parentMethodName]
                        }

                        // removed
                        if (curClassMethod == null && prevClassMethod.visible && !prevClassMethod.deprecated) {
                            if (classMethodName.contains("getActivityTitle")) {
                                println "hi!"
                            }
                            changedClassMethods.put(prevClassMethod, Change.REMOVED)
                        }
                    } else {
                        if (prevClassMethod.deprecated) {
                            deprecatedNotRemoved << prevClassMethod;
                        } else if (curClassMethod.deprecated) {
                            newlyDeprecated << prevClassMethod;
                        }
//                        println "changed: $classMethodName"
                    }
                }

                String prevClassName = null
                def introClass = { classMethod ->
                    if (classMethod.className != prevClassName) {
                        prevClassName = classMethod.className
                        println "\n$prevClassName:"
                    }
                }

                def entryPoints = project.checkApiChanges.entryPoints
                Closure matchesEntryPoint = { ClassMethod classMethod ->
                    for (String entryPoint : entryPoints) {
                        if (classMethod.className.matches(entryPoint)) {
                            return true
                        }
                    }
                    return false
                }

                def expectedREs = project.checkApiChanges.expectedChanges.collect { Pattern.compile(it) }

                for (Map.Entry<ClassMethod, Change> change : changedClassMethods.entrySet()) {
                    def classMethod = change.key
                    def changeType = change.value

                    def showAllChanges = true // todo: only show stuff that's interesting...
                    if (matchesEntryPoint(classMethod) || showAllChanges) {
                        String classMethodDesc = classMethod.desc
                        def expected = expectedREs.any { it.matcher(classMethodDesc).find() }
                        if (!expected) {
                            introClass(classMethod)

                            switch (changeType) {
                                case Change.ADDED:
                                    println "+ ${classMethod.methodDesc}"
                                    break
                                case Change.REMOVED:
                                    println "- ${classMethod.methodDesc}"
                                    break
                            }
                        }
                    }
                }

                if (!deprecatedNotRemoved.empty) {
                    println "\nDeprecated but not removed:"
                    for (ClassMethod classMethod : deprecatedNotRemoved) {
                        introClass(classMethod)
                        println "* ${classMethod.methodDesc}"
                    }
                }

                if (!newlyDeprecated.empty) {
                    println "\nNewly deprecated:"
                    for (ClassMethod classMethod : newlyDeprecated) {
                        introClass(classMethod)
                        println "* ${classMethod.methodDesc}"
                    }
                }
            }
        }
    }