Skip to content
GitLab
Explore
Sign in
Register
Commits on Source (2)
New upstream version 4.4
· c436267a
Kai-Chung Yan (Deprecated)
authored
May 12, 2018
c436267a
Re-import 4.4 to exclude *.a files
· 1f2273f0
Kai-Chung Yan (Deprecated)
authored
May 17, 2018
1f2273f0
Show whitespace changes
Inline
Side-by-side
Some changes are not shown.
For a faster browsing experience, only
20 of 1000+
files are shown.
build.gradle
View file @
1f2273f0
...
...
@@ -24,90 +24,69 @@ archivesBaseName = 'gradle'
buildTypes
{
sanityCheck
{
tasks
"classes"
,
"doc:checkstyleApi"
,
"codeQuality"
,
"docs:check"
}
// The minimum to be run before check-in
preCommitBuild
{
tasks
"doc:checkstyleApi"
,
"docs:check"
,
"codeQuality"
,
"test"
}
quickCheck
{
tasks
"doc:checkstyleApi"
,
"docs:check"
,
"codeQuality"
,
"test"
}
// For testing pull requests
pullRequestValidation
{
tasks
"doc:checkstyleApi"
,
"docs:check"
,
"codeQuality"
,
"core:test"
,
"dependencyManagement:test"
}
// A full (in-process) test
developerBuild
{
tasks
"check"
tasks
"classes"
,
"doc:checkstyleApi"
,
"codeQuality"
,
"docs:check"
,
"distribution:checkBinaryCompatibility"
,
"javadocAll"
projectProperties
ignoreIncomingBuildReceipt:
true
}
// Used by the first phase of the build pipeline, running only last version on multiversion - tests
quickTest
{
tasks
"
runtimeT
est
s
"
,
"
runtimeIntegTests
"
tasks
"
t
est"
,
"
integTest"
,
"crossVersionTest
"
}
// Used for builds to run all tests, but not necessarily on all platforms
fullTest
{
tasks
"
runtimeT
est
s
"
,
"
runtimeF
orkingIntegTest
s
"
projectProperties
useIncomingDistributions:
true
,
testAllVersions:
true
tasks
"
t
est"
,
"
f
orkingIntegTest
"
,
"forkingCrossVersionTest
"
projectProperties
testAllVersions:
true
}
// Used for builds to test the code on certain platforms
platformTest
{
tasks
"
runtimeT
est
s
"
,
"
runtimeF
orkingIntegTest
s
"
projectProperties
useIncomingDistributions:
true
,
testAllVersions:
true
,
testAllPlatforms:
true
tasks
"
t
est"
,
"
f
orkingIntegTest
"
,
"forkingCrossVersionTest
"
projectProperties
testAllVersions:
true
,
testAllPlatforms:
true
}
// Tests using the daemon mode
d
aemonTest
{
tasks
"
runtime
DaemonIntegTest
s
"
projectProperties
use
Incoming
Distribution
s
:
true
// Tests
not
using the daemon mode
noD
aemonTest
{
tasks
"
no
DaemonIntegTest"
projectProperties
use
All
Distribution:
true
}
// Run the integration tests using the parallel executer
parallelTest
{
tasks
"runtimeParallelIntegTests"
projectProperties
useIncomingDistributions:
true
tasks
"parallelIntegTest"
}
performanceTests
{
tasks
"performance:performanceTest"
projectProperties
useIncomingDistributions:
true
}
performanceExperiments
{
tasks
"performance:performanceExperiments"
projectProperties
useIncomingDistributions:
true
}
fullPerformanceTests
{
tasks
"performance:fullPerformanceTest"
projectProperties
useIncomingDistributions:
true
}
distributedPerformanceTests
{
tasks
"performance:distributedPerformanceTest"
projectProperties
useIncomingDistributions:
true
}
distributedPerformanceExperiments
{
tasks
"performance:distributedPerformanceExperiment"
projectProperties
useIncomingDistributions:
true
}
distributedFullPerformanceTests
{
tasks
"performance:distributedFullPerformanceTest"
projectProperties
useIncomingDistributions:
true
}
// Used for cross version tests on CI
crossVersionTest
{
tasks
"crossVersionIntegTest"
projectProperties
useIncomingDistributions:
true
allVersionsCrossVersionTest
{
tasks
"allVersionsCrossVersionTests"
}
quickFeedbackCrossVersionTest
{
tasks
"quickFeedbackCrossVersionTests"
}
// Used to build production distros and smoke test them
...
...
@@ -115,11 +94,6 @@ buildTypes {
tasks
"verifyIsProductionBuildEnvironment"
,
"clean"
,
"buildDists"
,
"distributions:integTest"
}
// Used to build (experimental) production distros and smoke test them
packageBuildExperimental
{
tasks
"verifyIsProductionBuildEnvironment"
,
"buildDists"
,
"distributions:integTest"
}
// Used to build production distros and smoke test them
promotionBuild
{
tasks
"verifyIsProductionBuildEnvironment"
,
"clean"
,
"docs:check"
,
"buildDists"
,
"distributions:integTest"
,
"uploadArchives"
...
...
@@ -128,7 +102,10 @@ buildTypes {
//Initial smoke test for java 9
java9Build
{
tasks
"java9Test"
,
"java9IntegTest"
projectProperties
useIncomingDistributions:
true
}
java9SmokeTest
{
tasks
"java9IntegTest"
}
soakTest
{
...
...
@@ -137,25 +114,22 @@ buildTypes {
}
}
apply
from:
"gradle/testGroupings.gradle"
apply
from:
'gradle/buildSplits.gradle'
apply
from:
'gradle/buildScanUserData.gradle'
ext
{
jvm
=
org
.
gradle
.
internal
.
jvm
.
Jvm
.
current
()
javaVersion
=
JavaVersion
.
current
()
isCiServer
=
System
.
getenv
().
containsKey
(
"
TEAMCITY_VERSION
"
)
isCiServer
=
System
.
getenv
().
containsKey
(
"
CI
"
)
isWindows
=
org
.
gradle
.
internal
.
os
.
OperatingSystem
.
current
().
windows
if
(
project
.
hasProperty
(
"maxParallelForks"
))
{
project
.
maxParallelForks
=
Integer
.
valueOf
(
project
.
maxParallelForks
,
10
)
}
else
{
ext
.
maxParallelForks
=
1
ext
.
maxParallelForks
=
4
}
if
(
project
.
hasProperty
(
"use
Incoming
Distribution
s
"
))
{
project
.
use
Incoming
Distribution
s
=
true
if
(
project
.
hasProperty
(
"use
All
Distribution"
))
{
project
.
use
All
Distribution
=
true
}
else
{
ext
.
use
Incoming
Distribution
s
=
false
ext
.
use
All
Distribution
=
false
}
agentNum
=
1
...
...
@@ -170,19 +144,21 @@ ext {
groovyProjects
=
subprojects
publicGroovyProjects
=
groovyProjects
-
internalProjects
pluginProjects
=
[
'plugins'
,
'codeQuality'
,
'jetty'
,
'antlr'
,
'wrapper'
,
'osgi'
,
'maven'
,
'plugins'
,
'codeQuality'
,
'antlr'
,
'wrapper'
,
'osgi'
,
'maven'
,
'ide'
,
'announce'
,
'scala'
,
'signing'
,
'ear'
,
'javascript'
,
'buildComparison'
,
'diagnostics'
,
'reporting'
,
'publish'
,
'ivy'
,
'jacoco'
,
'buildInit'
,
'platformBase'
,
'platformJvm'
,
'languageJvm'
,
'languageJava'
,
'languageGroovy'
,
'languageScala'
,
'platformNative'
,
'platformPlay'
,
'idePlay'
,
'languageNative'
,
'ideNative'
,
'testingBase'
,
'testingNative'
,
'testingJvm'
,
'pluginDevelopment'
,
'pluginUse'
,
'resourcesHttp'
,
'resourcesSftp'
,
'resourcesS3'
,
'toolingApiBuilders'
,
'compositeBuilds'
,
'buildCacheHttp'
].
collect
{
project
(
it
)
}
'resourcesSftp'
,
'resourcesS3'
,
'resourcesGcs'
,
'compositeBuilds'
,
'buildCacheHttp'
].
collect
{
project
(
it
)
}
implementationPluginProjects
=
[
project
(
'toolingApiBuilders'
)
]
publishedProjects
=
[
project
(
':logging'
),
project
(
':core'
),
project
(
':modelCore'
),
project
(
':toolingApi'
),
project
(
':wrapper'
),
project
(
':baseServices'
),
...
...
@@ -193,10 +169,10 @@ ext {
project
(
':processServices'
),
project
(
':resources'
)
]
removedProjects
=
[
'sonar'
]
}
apply
from:
"gradle/incomingDistributions.gradle"
apply
from:
"gradle/buildScanUserData.gradle"
apply
from:
"gradle/taskCacheBuildScanUserData.gradle"
apply
from:
"gradle/versioning.gradle"
apply
from:
"gradle/dependencies.gradle"
apply
from:
"gradle/wrapper.gradle"
...
...
@@ -206,9 +182,10 @@ apply from: "gradle/classycle.gradle"
apply
from:
"gradle/strictCompile.gradle"
apply
from:
"gradle/noDependencyResolutionDuringConfiguration.gradle"
apply
from:
"gradle/testSetup.gradle"
apply
from:
"gradle/taskOrdering.gradle"
apply
from:
"gradle/fix-GRADLE-2492.gradle"
apply
from:
'gradle/customM2Check.gradle'
apply
from:
"gradle/publicApi.gradle"
apply
from:
"gradle/updateReleasedVersions.gradle"
allprojects
{
group
=
'org.gradle'
...
...
@@ -216,16 +193,13 @@ allprojects {
repositories
{
maven
{
url
'https://repo.gradle.org/gradle/libs-releases'
}
maven
{
url
'https://repo.gradle.org/gradle/libs-milestones'
}
maven
{
url
"https://repo.gradle.org/gradle/libs-snapshots"
}
}
// Force clean tasks to run before any other tasks
tasks
.
withType
(
Delete
)
{
cleanTask
->
tasks
.
all
{
otherTask
->
if
(
cleanTask
!=
otherTask
&&
!(
otherTask
instanceof
Delete
)
&&
!(
otherTask
.
name
in
[
'killExistingDaemons'
,
'tasks'
]))
{
otherTask
.
mustRunAfter
cleanTask
}
// patchExternalModules lives in the root project - we need to activate normalization there, too.
normalization
{
runtimeClasspath
{
ignore
'org/gradle/build-receipt.properties'
}
}
}
...
...
@@ -246,16 +220,15 @@ subprojects {
}
apply
from:
"$rootDir/gradle/codeQuality.gradle"
if
(
isCiServer
)
{
reporting
.
baseDir
"$rootProject.reporting.baseDir/${path.replaceFirst(':', '').replaceAll(':', '.')}"
}
}
configurations
{
coreRuntime
{
visible
=
false
}
coreRuntimeExtensions
{
visible
=
false
}
externalModules
{
visible
=
false
}
...
...
@@ -284,27 +257,32 @@ def patchedExternalModules = files({ -> fileTree(patchedExternalModulesDir).file
patchedExternalModules
.
builtBy
'patchExternalModules'
dependencies
{
externalModules
'org.gradle:gradle-script-kotlin:0.5.1'
externalModules
"org.gradle:gradle-kotlin-dsl:${versions.gradle_kotlin_dsl}"
externalModules
"org.gradle:gradle-kotlin-dsl-tooling-builders:${versions.gradle_kotlin_dsl}"
coreRuntime
project
(
':launcher'
)
coreRuntime
project
(
':runtimeApiInfo'
)
runtime
project
(
':wrapper'
)
runtime
project
(
":installationBeacon"
)
runtime
patchedExternalModules
gradlePlugins
pluginProjects
gradlePlugins
implementationPluginProjects
gradlePlugins
project
(
':workers'
)
gradlePlugins
project
(
':dependencyManagement'
)
gradlePlugins
project
(
':testKit'
)
coreRuntimeExtensions
project
(
':dependencyManagement'
)
//See: DynamicModulesClassPathProvider.GRADLE_EXTENSION_MODULES
coreRuntimeExtensions
project
(
':pluginUse'
)
coreRuntimeExtensions
project
(
':workers'
)
coreRuntimeExtensions
patchedExternalModules
}
import
org.gradle.modules.PatchExternalModules
task
patchExternalModules
(
type:
PatchExternalModules
)
{
// Include any dependency jars that are not available in the core runtime
externalModulesRuntime
=
configurations
.
externalModulesRuntime
coreRuntime
=
configurations
.
coreRuntime
externalModules
=
configurations
.
externalModules
allModules
=
configurations
.
externalModulesRuntime
coreModules
=
configurations
.
coreRuntime
modulesToPatch
=
configurations
.
externalModules
destination
=
patchedExternalModulesDir
dependsOn
configurations
.
externalModules
}
task
verifyIsProductionBuildEnvironment
{
...
...
@@ -315,26 +293,12 @@ task verifyIsProductionBuildEnvironment {
}
}
task
waitForDaemonsToDie
{
if
(!
project
.
hasProperty
(
"noWaitForDaemonsToDie"
))
{
if
(
isWindows
&&
isCiServer
&&
buildTypes
.
crossVersionTest
.
active
)
{
gradle
.
startParameter
.
taskNames
.
add
(
0
,
it
.
path
)
}
doLast
{
def
mins
=
2
println
"I'm waiting for $mins mins so that existing daemons can die with honour. It's a workaround until we fix it properly."
sleep
mins
*
60
*
1000
}
}
}
evaluationDependsOn
":distributions"
task
install
(
type:
Install
)
{
description
=
'Installs the minimal distribution into directory $gradle_installPath'
group
=
'build'
with
project
(
":distributions"
).
binDistImage
with
project
(
":distributions"
).
versionInfo
installDirPropertyName
=
'gradle_installPath'
}
...
...
@@ -345,13 +309,6 @@ task installAll(type: Install) {
installDirPropertyName
=
'gradle_installPath'
}
clean
{
dependsOn
':killExistingDaemons'
}
apply
from:
"gradle/intTestImage.gradle"
apply
from:
'gradle/pullRequestBuild.gradle'
// Generate a report showing which tests in a subproject are leaving
// files around.
//
...
...
@@ -368,35 +325,11 @@ subprojects { prj ->
}
}
task
cleanUpRemovedProjects
(
type:
Delete
)
{
delete
removedProjects
.
collect
{
"subprojects/$it"
}
}
clean
.
dependsOn
(
cleanUpRemovedProjects
)
/*
* When run from a Continuous Integration environment HTML test reports will usually only be inspected
* if the build failed e.g. due to failed or flaky tests.
*
* Deletes HTML test reports so they are not archived on TeamCity and use up unnecessary disk space.
*/
if
(
isCiServer
)
{
gradle
.
buildFinished
{
buildResult
->
if
(!
buildResult
.
failure
)
{
logger
.
quiet
"Deleting HTML test reports..."
subprojects
{
def
htmlTestReportDirs
=
tasks
.
withType
(
Test
).
collect
{
it
.
reports
.
html
.
destination
}.
unique
()
htmlTestReportDirs
.
each
{
htmlReportDir
->
logger
.
info
"Deleting test reports directory '$htmlReportDir'."
def
success
=
htmlReportDir
.
deleteDir
()
if
(!
success
)
{
logger
.
warn
"Unable to delete test report directory '$htmlReportDir'."
}
}
}
}
gradle
.
buildFinished
{
result
->
def
rootProject
=
result
.
gradle
.
rootProject
if
(
rootProject
.
remoteBuildCacheEnabled
&&
!
rootProject
.
java7HomeSet
)
{
logger
.
warn
(
"In order to have cache hits from the remote build cache you need to set 'java7Home' in your gradle.properties!"
)
}
}
apply
from:
"gradle/ciReporting.gradle"
buildSrc/build.gradle
View file @
1f2273f0
...
...
@@ -21,8 +21,14 @@ apply plugin: 'eclipse'
sourceCompatibility
=
'1.7'
targetCompatibility
=
'1.7'
// 1.5.3 has a classloader leak (https://github.com/asciidoctor/asciidoctor-gradle-plugin/pull/215)
// 1.5.6 requires Java 8+ (https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/218)
def
asciidoctorPluginVersion
=
JavaVersion
.
current
()
==
JavaVersion
.
VERSION_1_7
?
'1.5.3'
:
'1.5.6'
repositories
{
maven
{
url
'https://repo.gradle.org/gradle/libs-releases'
}
maven
{
url
"https://repo.gradle.org/gradle/libs-snapshots"
}
maven
{
url
"https://plugins.gradle.org/m2/"
}
}
dependencies
{
...
...
@@ -36,20 +42,24 @@ dependencies {
exclude
(
module:
'xercesImpl'
)
}
testCompile
'junit:junit:4.12@jar'
testCompile
'org.spockframework:spock-core:1.0-groovy-2.4@jar'
,
'cglib:cglib-nodep:
2
.2'
,
'org.objenesis:objenesis:1.2'
testCompile
'org.spockframework:spock-core:1.0-groovy-2.4@jar'
,
'cglib:cglib-nodep:
3
.2
.5
'
,
'org.objenesis:objenesis:1.2'
testCompile
'org.hamcrest:hamcrest-core:1.3'
compile
"org.pegdown:pegdown:1.6.0"
compile
"org.jsoup:jsoup:1.6.3"
compile
'me.champeau.gradle:japicmp-gradle-plugin:0.2.4'
compile
"org.asciidoctor:asciidoctor-gradle-plugin:$asciidoctorPluginVersion"
compile
'com.github.javaparser:javaparser-core:2.4.0'
}
ext
.
isCiServer
=
System
.
getenv
().
containsKey
(
"CI"
)
apply
from:
'../gradle/compile.gradle'
apply
from:
'../gradle/taskOrdering.gradle'
apply
from:
'../gradle/dependencies.gradle'
apply
from:
'../gradle/classycle.gradle'
ext
.
isCiServer
=
System
.
getenv
().
containsKey
(
"TEAMCITY_VERSION"
)
if
(!
isCiServer
||
(
isCiServer
&&
Boolean
.
getBoolean
(
'enableCodeQuality'
)))
{
apply
from:
'../gradle/codeQuality.gradle'
}
apply
from:
"../gradle/ciReporting.gradle"
buildSrc/settings.gradle
View file @
1f2273f0
...
...
@@ -14,7 +14,4 @@
* limitations under the License.
*/
if
(
gradle
.
startParameter
.
systemPropertiesArgs
.
containsKey
(
"gradle.cache.remote.url"
))
{
println
"Applying remoteHttpCacheInit to buildSrc"
apply
from:
new
File
(
settingsDir
,
'../gradle/remoteHttpCacheInit.gradle'
)
}
apply
from:
new
File
(
settingsDir
,
'../gradle/remoteHttpCacheSettings.gradle'
)
buildSrc/src/main/groovy/org/gradle/binarycompatibility/AcceptedApiChanges.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility
import
groovy.json.JsonOutput
import
groovy.json.JsonSlurper
import
org.gradle.util.GradleVersion
class
AcceptedApiChanges
{
GradleVersion
baseVersion
Map
<
ApiChange
,
String
>
acceptedChanges
static
AcceptedApiChanges
parse
(
String
jsonText
)
{
def
json
=
new
JsonSlurper
().
parseText
(
jsonText
)
def
acceptedApiChanges
=
new
AcceptedApiChanges
()
acceptedApiChanges
.
acceptedChanges
=
json
.
acceptedApiChanges
.
collectEntries
{
jsonChange
->
[(
ApiChange
.
parse
(
jsonChange
)):
jsonChange
.
acceptation
]
}
return
acceptedApiChanges
}
Map
<
String
,
String
>
toAcceptedChangesMap
()
{
acceptedChanges
.
collectEntries
{
change
->
[(
JsonOutput
.
toJson
(
change
.
key
)):
change
.
value
]
}
}
static
Map
<
ApiChange
,
String
>
fromAcceptedChangesMap
(
Map
<
String
,
String
>
acceptedChanges
)
{
acceptedChanges
.
collectEntries
{
key
,
value
->
[(
ApiChange
.
parse
(
new
JsonSlurper
().
parseText
(
key
))):
value
]
}
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/ApiChange.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility
import
groovy.transform.Immutable
@Immutable
class
ApiChange
{
String
type
String
member
List
<
String
>
changes
static
ApiChange
parse
(
Object
json
)
{
new
ApiChange
(
json
.
type
,
json
.
member
,
json
.
changes
?:
[])
}
String
toString
()
{
def
formattedMember
=
member
-
"$type."
"$type - $formattedMember - $changes"
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/AbstractGradleViolationRule.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
import
com.github.javaparser.JavaParser
import
com.github.javaparser.ast.body.MethodDeclaration
import
com.github.javaparser.ast.visitor.GenericVisitorAdapter
import
groovy.json.JsonOutput
import
groovy.transform.CompileStatic
import
japicmp.model.JApiClass
import
japicmp.model.JApiCompatibility
import
japicmp.model.JApiConstructor
import
japicmp.model.JApiField
import
japicmp.model.JApiHasAnnotations
import
japicmp.model.JApiMethod
import
me.champeau.gradle.japicmp.report.AbstractContextAwareViolationRule
import
me.champeau.gradle.japicmp.report.Violation
import
org.gradle.api.Incubating
import
org.gradle.binarycompatibility.AcceptedApiChanges
import
org.gradle.binarycompatibility.ApiChange
import
javax.inject.Inject
@CompileStatic
abstract
class
AbstractGradleViolationRule
extends
AbstractContextAwareViolationRule
{
private
final
Map
<
ApiChange
,
String
>
acceptedApiChanges
AbstractGradleViolationRule
(
Map
<
String
,
String
>
acceptedApiChanges
)
{
this
.
acceptedApiChanges
=
AcceptedApiChanges
.
fromAcceptedChangesMap
(
acceptedApiChanges
)
}
private
static
boolean
isAnnotatedWithIncubating
(
JApiHasAnnotations
member
)
{
member
.
annotations
*.
fullyQualifiedName
.
any
{
it
==
Incubating
.
name
}
}
private
static
boolean
isAnnotatedWithDeprecated
(
JApiHasAnnotations
member
)
{
member
.
annotations
*.
fullyQualifiedName
.
any
{
it
==
Deprecated
.
name
}
}
private
static
boolean
isAnnotatedWithInject
(
JApiHasAnnotations
member
)
{
member
.
annotations
*.
fullyQualifiedName
.
any
{
it
==
Inject
.
name
}
}
boolean
isInject
(
JApiHasAnnotations
member
)
{
return
isAnnotatedWithInject
(
member
)
}
boolean
isIncubatingOrDeprecated
(
JApiHasAnnotations
member
)
{
if
(
member
instanceof
JApiClass
)
{
return
isIncubatingOrDeprecated
((
JApiClass
)
member
)
}
else
if
(
member
instanceof
JApiMethod
)
{
return
isIncubatingOrDeprecatedOrOverride
((
JApiMethod
)
member
)
}
else
if
(
member
instanceof
JApiField
)
{
return
isIncubatingOrDeprecated
((
JApiField
)
member
)
}
else
if
(
member
instanceof
JApiConstructor
)
{
return
isIncubatingOrDeprecated
((
JApiConstructor
)
member
)
}
return
isAnnotatedWithIncubating
(
member
)
}
boolean
isIncubatingOrDeprecated
(
JApiClass
clazz
)
{
return
isAnnotatedWithIncubating
(
clazz
)
||
isAnnotatedWithDeprecated
(
clazz
)
}
boolean
isIncubatingOrDeprecated
(
JApiField
field
)
{
return
isAnnotatedWithIncubating
(
field
)
||
isAnnotatedWithIncubating
(
field
.
jApiClass
)
||
isAnnotatedWithDeprecated
(
field
)
||
isAnnotatedWithDeprecated
(
field
.
jApiClass
)
}
boolean
isIncubatingOrDeprecated
(
JApiConstructor
constructor
)
{
return
isAnnotatedWithIncubating
(
constructor
)
||
isAnnotatedWithIncubating
(
constructor
.
jApiClass
)
||
isAnnotatedWithDeprecated
(
constructor
)
||
isAnnotatedWithDeprecated
(
constructor
.
jApiClass
)
}
boolean
isIncubatingOrDeprecatedOrOverride
(
JApiMethod
method
)
{
return
isAnnotatedWithIncubating
(
method
)
||
isAnnotatedWithIncubating
(
method
.
jApiClass
)
||
isOverride
(
method
)
||
isAnnotatedWithDeprecated
(
method
)
||
isAnnotatedWithDeprecated
(
method
.
jApiClass
)
}
boolean
isDeprecated
(
JApiClass
clazz
)
{
return
isAnnotatedWithDeprecated
(
clazz
)
}
boolean
isDeprecated
(
JApiConstructor
constructor
)
{
return
isAnnotatedWithDeprecated
(
constructor
)
||
isAnnotatedWithDeprecated
(
constructor
.
jApiClass
)
}
boolean
isDeprecated
(
JApiField
field
)
{
return
isAnnotatedWithDeprecated
(
field
)
||
isAnnotatedWithDeprecated
(
field
.
jApiClass
)
}
boolean
isDeprecated
(
JApiMethod
method
)
{
return
isAnnotatedWithDeprecated
(
method
)
||
isAnnotatedWithDeprecated
(
method
.
jApiClass
)
}
boolean
isOverride
(
JApiMethod
method
)
{
// @Override has source retention - so we need to peek into the sources
def
visitor
=
new
GenericVisitorAdapter
<
Object
,
Void
>()
{
@Override
Object
visit
(
MethodDeclaration
declaration
,
Void
arg
)
{
if
(
declaration
.
name
==
method
.
name
&&
declaration
.
annotations
.
any
{
it
.
name
.
name
==
Override
.
simpleName
}
)
{
return
new
Object
()
}
return
null
}
}
return
JavaParser
.
parse
(
sourceFileFor
(
method
.
jApiClass
.
fullyQualifiedName
)).
accept
(
visitor
,
null
)
!=
null
}
File
sourceFileFor
(
String
className
)
{
List
<
String
>
sourceFolders
=
context
.
userData
.
get
(
"apiSourceFolders"
)
as
List
<
String
>
for
(
String
sourceFolder
:
sourceFolders
)
{
def
sourceFilePath
=
className
.
replace
(
'.'
,
'/'
).
replaceAll
(
'\\$.*'
,
''
)
def
sourceFile
=
new
File
(
"$sourceFolder/${sourceFilePath}.java"
)
if
(
sourceFile
.
exists
())
{
return
sourceFile
}
}
throw
new
RuntimeException
(
"No source file found for: $className"
)
}
Violation
acceptOrReject
(
JApiCompatibility
member
,
Violation
rejection
)
{
List
<
String
>
changes
=
member
.
compatibilityChanges
.
collect
{
Violation
.
describe
(
it
)
}
return
acceptOrReject
(
member
,
changes
,
rejection
)
}
Violation
acceptOrReject
(
JApiCompatibility
member
,
List
<
String
>
changes
,
Violation
rejection
)
{
Set
<
ApiChange
>
seenApiChanges
=
(
Set
<
ApiChange
>)
context
.
userData
[
"seenApiChanges"
]
def
change
=
new
ApiChange
(
context
.
className
,
Violation
.
describe
(
member
),
changes
)
String
acceptationReason
=
acceptedApiChanges
[
change
]
if
(
acceptationReason
!=
null
)
{
seenApiChanges
.
add
(
change
)
return
Violation
.
accept
(
member
,
"${rejection.getHumanExplanation()}. Reason for accepting this: <b>$acceptationReason</b>"
)
}
def
acceptanceJson
=
new
LinkedHashMap
<
String
,
Object
>([
type:
change
.
type
,
member:
change
.
member
,
acceptation:
'<ADD YOUR CUSTOM REASON HERE>'
])
if
(
change
.
changes
)
{
acceptanceJson
.
changes
=
change
.
changes
}
def
id
=
"accept"
+
(
change
.
type
+
change
.
member
).
replaceAll
(
'[^a-zA-Z0-9]'
,
'_'
)
Violation
violation
=
Violation
.
error
(
member
,
rejection
.
getHumanExplanation
()
+
""". If you did this intentionally, please accept the change and provide an explanation:
<a class="btn btn-info" role="button" data-toggle="collapse" href="#${id}" aria-expanded="false" aria-controls="collapseExample">Accept this change</a>
<div class="collapse" id="${id}">
<div class="well">
In order to accept this change add the following to <code>subprojects/distributions/src/changes/accepted-public-api-changes.json</code>:
<pre>${JsonOutput.prettyPrint(JsonOutput.toJson(acceptanceJson))}</pre>
</div>
</div>"""
.
stripIndent
()
)
return
violation
}
String
getCurrentVersion
()
{
return
context
.
getUserData
().
get
(
"currentVersion"
)
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/AbstractSuperClassChangesRule.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
import
me.champeau.gradle.japicmp.report.Violation
import
japicmp.model.JApiClass
import
japicmp.model.JApiCompatibility
import
javassist.CtClass
import
com.google.common.base.Optional
import
java.util.regex.Pattern
abstract
class
AbstractSuperClassChangesRule
extends
AbstractGradleViolationRule
{
private
final
List
<
Pattern
>
publicApiPatterns
AbstractSuperClassChangesRule
(
Map
params
)
{
super
(
params
[
'acceptedApiChanges'
])
this
.
publicApiPatterns
=
params
[
'publicApiPatterns'
].
collect
{
Pattern
.
compile
(
it
)
}
}
Violation
maybeViolation
(
final
JApiCompatibility
member
)
{
if
(!(
member
instanceof
JApiClass
))
{
return
null
}
if
(!
changed
(
member
))
{
return
null
}
Optional
<
CtClass
>
oldClass
=
member
.
oldClass
Optional
<
CtClass
>
newClass
=
member
.
newClass
if
(!
oldClass
.
isPresent
()
||
!
newClass
.
isPresent
())
{
// breaking change would be reported
return
null
}
return
checkSuperClassChanges
(
member
,
oldClass
.
get
(),
newClass
.
get
())
}
protected
abstract
boolean
changed
(
JApiCompatibility
member
)
protected
abstract
Violation
checkSuperClassChanges
(
JApiClass
apiClass
,
CtClass
oldClass
,
CtClass
newClass
)
protected
boolean
isInternal
(
CtClass
c
)
{
if
(
c
.
name
.
contains
(
'.internal.'
))
{
return
true
}
else
{
return
!
publicApiPatterns
.
any
{
it
.
matcher
(
c
.
name
).
find
()
}
}
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/AcceptedRegressionsRulePostProcess.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
me.champeau.gradle.japicmp.report.PostProcessViolationsRule
;
import
me.champeau.gradle.japicmp.report.ViolationCheckContextWithViolations
;
import
org.gradle.binarycompatibility.ApiChange
;
import
org.gradle.util.CollectionUtils
;
import
java.util.HashSet
;
import
java.util.Set
;
public
class
AcceptedRegressionsRulePostProcess
implements
PostProcessViolationsRule
{
@SuppressWarnings
(
"unchecked"
)
public
void
execute
(
ViolationCheckContextWithViolations
context
)
{
Set
<
ApiChange
>
acceptedApiChanges
=
(
Set
<
ApiChange
>)
context
.
getUserData
().
get
(
"acceptedApiChanges"
);
Set
<
ApiChange
>
seenApiChanges
=
(
Set
<
ApiChange
>)
context
.
getUserData
().
get
(
"seenApiChanges"
);
Set
<
ApiChange
>
left
=
new
HashSet
<>(
acceptedApiChanges
);
left
.
removeAll
(
seenApiChanges
);
if
(!
left
.
isEmpty
())
{
String
formattedLeft
=
CollectionUtils
.
join
(
"\n"
,
left
);
throw
new
RuntimeException
(
"The following regressions are declared as accepted, but didn't match any rule:\n\n"
+
formattedLeft
);
}
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/AcceptedRegressionsRuleSetup.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
me.champeau.gradle.japicmp.report.SetupRule
;
import
me.champeau.gradle.japicmp.report.ViolationCheckContext
;
import
org.gradle.binarycompatibility.AcceptedApiChanges
;
import
org.gradle.binarycompatibility.ApiChange
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.Set
;
public
class
AcceptedRegressionsRuleSetup
implements
SetupRule
{
private
final
Set
<
ApiChange
>
acceptedApiChanges
;
public
AcceptedRegressionsRuleSetup
(
Map
<
String
,
String
>
acceptedApiChanges
)
{
this
.
acceptedApiChanges
=
AcceptedApiChanges
.
fromAcceptedChangesMap
(
acceptedApiChanges
).
keySet
();
}
@SuppressWarnings
(
"unchecked"
)
public
void
execute
(
ViolationCheckContext
context
)
{
Map
<
String
,
Object
>
userData
=
(
Map
<
String
,
Object
>)
context
.
getUserData
();
userData
.
put
(
"acceptedApiChanges"
,
acceptedApiChanges
);
userData
.
put
(
"seenApiChanges"
,
new
HashSet
<
ApiChange
>());
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/BinaryBreakingChangesRule.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
com.google.common.collect.ImmutableList
;
import
japicmp.model.JApiClass
;
import
japicmp.model.JApiCompatibility
;
import
japicmp.model.JApiCompatibilityChange
;
import
japicmp.model.JApiConstructor
;
import
japicmp.model.JApiHasAnnotations
;
import
japicmp.model.JApiImplementedInterface
;
import
me.champeau.gradle.japicmp.report.Violation
;
import
java.util.List
;
import
java.util.Map
;
public
class
BinaryBreakingChangesRule
extends
AbstractGradleViolationRule
{
private
static
final
List
<
JApiCompatibilityChange
>
IGNORED_CHANGE_TYPES
=
ImmutableList
.
of
(
JApiCompatibilityChange
.
METHOD_REMOVED_IN_SUPERCLASS
,
// the removal of the method will be reported
JApiCompatibilityChange
.
INTERFACE_REMOVED
,
// the removed methods will be reported
JApiCompatibilityChange
.
INTERFACE_ADDED
// the added methods will be reported
);
public
BinaryBreakingChangesRule
(
Map
<
String
,
String
>
acceptedApiChanges
)
{
super
(
acceptedApiChanges
);
}
@Override
@SuppressWarnings
(
"unchecked"
)
public
Violation
maybeViolation
(
final
JApiCompatibility
member
)
{
if
(!
member
.
isBinaryCompatible
())
{
if
((
member
instanceof
JApiClass
)
&&
(
member
.
getCompatibilityChanges
().
isEmpty
()))
{
// A member of the class breaks binary compatibility.
// That will be handled when the member is passed to `maybeViolation`.
return
null
;
}
if
(
member
instanceof
JApiImplementedInterface
)
{
// The changes about the interface's methods will be reported already
return
null
;
}
if
(
member
instanceof
JApiConstructor
)
{
if
(
isInject
((
JApiConstructor
)
member
))
{
// We do not consider injecting constructors public API
return
null
;
}
}
for
(
JApiCompatibilityChange
change
:
member
.
getCompatibilityChanges
())
{
if
(
IGNORED_CHANGE_TYPES
.
contains
(
change
))
{
return
null
;
}
}
if
(
member
instanceof
JApiHasAnnotations
)
{
if
(
isIncubatingOrDeprecated
((
JApiHasAnnotations
)
member
))
{
return
Violation
.
warning
(
member
,
"Changed public API (@Incubating)"
);
}
}
return
acceptOrReject
(
member
,
Violation
.
notBinaryCompatible
(
member
));
}
return
null
;
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/IncubatingInternalInterfaceAddedRule.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
import
me.champeau.gradle.japicmp.report.Violation
import
japicmp.model.JApiClass
import
japicmp.model.JApiChangeStatus
import
japicmp.model.JApiCompatibility
import
javassist.CtClass
class
IncubatingInternalInterfaceAddedRule
extends
AbstractSuperClassChangesRule
{
IncubatingInternalInterfaceAddedRule
(
Map
params
)
{
super
(
params
)
}
protected
boolean
changed
(
JApiCompatibility
member
)
{
return
member
.
getChangeStatus
()
==
JApiChangeStatus
.
MODIFIED
}
protected
Violation
checkSuperClassChanges
(
JApiClass
c
,
CtClass
oldClass
,
CtClass
newClass
)
{
Map
<
String
,
CtClass
>
oldInterfaces
=
collectImplementedInterfaces
(
oldClass
)
Map
<
String
,
CtClass
>
newInterfaces
=
collectImplementedInterfaces
(
newClass
)
newInterfaces
.
keySet
().
removeAll
(
oldInterfaces
.
keySet
())
if
(
newInterfaces
.
isEmpty
())
{
return
null
}
List
<
String
>
changes
=
filterChangesToReport
(
newClass
,
newInterfaces
)
if
(
changes
.
isEmpty
())
{
return
null
}
return
acceptOrReject
(
c
,
changes
,
Violation
.
error
(
c
,
" introduces internal or incubating interfaces"
))
}
private
Map
<
String
,
CtClass
>
collectImplementedInterfaces
(
CtClass
c
)
{
Map
<
String
,
CtClass
>
result
=
[:]
collect
(
result
,
c
)
return
result
}
private
void
collect
(
Map
<
String
,
CtClass
>
result
,
CtClass
c
)
{
c
.
interfaces
.
each
{
result
.
put
(
it
.
name
,
it
)
}
if
(
c
.
superclass
!=
null
)
{
collect
(
result
,
c
.
superclass
)
}
}
private
List
<
String
>
filterChangesToReport
(
CtClass
c
,
Map
<
String
,
CtClass
>
interfaces
)
{
return
interfaces
.
values
().
findAll
{
implementedDirectly
(
it
,
c
)
&&
addedInterfaceIsIncubatingOrInternal
(
it
,
c
)
}*.
name
.
sort
()
}
private
boolean
implementedDirectly
(
CtClass
interf
,
CtClass
c
)
{
return
c
.
interfaces
.
any
{
it
.
name
==
interf
.
name
}
}
private
boolean
addedInterfaceIsIncubatingOrInternal
(
CtClass
interf
,
CtClass
c
)
{
return
(
isIncubating
(
interf
)
&&
!
isIncubating
(
c
))
||
isInternal
(
interf
)
}
private
boolean
isIncubating
(
CtClass
c
)
{
return
c
.
annotations
.
any
{
it
.
annotationType
().
name
==
'org.gradle.api.Incubating'
}
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/IncubatingMissingRule.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
japicmp.model.JApiClass
;
import
japicmp.model.JApiCompatibility
;
import
japicmp.model.JApiConstructor
;
import
japicmp.model.JApiField
;
import
japicmp.model.JApiHasAnnotations
;
import
japicmp.model.JApiMethod
;
import
me.champeau.gradle.japicmp.report.Violation
;
import
java.util.Map
;
public
class
IncubatingMissingRule
extends
AbstractGradleViolationRule
{
public
IncubatingMissingRule
(
Map
<
String
,
String
>
acceptedViolations
)
{
super
(
acceptedViolations
);
}
@Override
public
Violation
maybeViolation
(
final
JApiCompatibility
member
)
{
if
(
member
instanceof
JApiMethod
||
member
instanceof
JApiField
||
member
instanceof
JApiClass
||
member
instanceof
JApiConstructor
)
{
if
(!
isIncubatingOrDeprecated
((
JApiHasAnnotations
)
member
))
{
return
violationError
(
member
);
}
}
return
null
;
}
private
Violation
violationError
(
JApiCompatibility
member
)
{
return
acceptOrReject
(
member
,
Violation
.
error
(
member
,
"Is not annotated with @Incubating"
));
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/MethodsRemovedInInternalSuperClassRule.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
import
me.champeau.gradle.japicmp.report.Violation
import
japicmp.model.JApiClass
import
japicmp.model.JApiCompatibility
import
japicmp.model.JApiCompatibilityChange
import
javassist.CtClass
import
javassist.CtMethod
import
javassist.Modifier
class
MethodsRemovedInInternalSuperClassRule
extends
AbstractSuperClassChangesRule
{
MethodsRemovedInInternalSuperClassRule
(
Map
params
)
{
super
(
params
)
}
protected
boolean
changed
(
JApiCompatibility
member
)
{
return
member
.
compatibilityChanges
.
contains
(
JApiCompatibilityChange
.
METHOD_REMOVED_IN_SUPERCLASS
)
}
protected
Violation
checkSuperClassChanges
(
JApiClass
c
,
CtClass
oldClass
,
CtClass
newClass
)
{
Set
<
CtMethod
>
oldMethods
=
collectAllPublicApiMethods
(
oldClass
)
Set
<
CtMethod
>
newMethods
=
collectAllPublicApiMethods
(
newClass
)
oldMethods
.
removeAll
(
newMethods
)
if
(
oldMethods
.
isEmpty
())
{
return
null
}
List
<
String
>
changes
=
filterChangesToReport
(
oldClass
,
oldMethods
)
if
(
changes
.
isEmpty
())
{
return
null
}
return
acceptOrReject
(
c
,
changes
,
Violation
.
error
(
c
,
" methods removed in internal super class"
))
}
private
Set
<
CtMethod
>
collectAllPublicApiMethods
(
CtClass
c
)
{
Set
<
CtMethod
>
result
=
[]
as
Set
collect
(
result
,
c
.
superclass
)
return
result
}
private
void
collect
(
Set
<
CtMethod
>
result
,
CtClass
c
)
{
if
(
c
==
null
)
{
return
}
result
.
addAll
(
c
.
declaredMethods
.
findAll
{
isPublicApi
(
it
)
})
collect
(
result
,
c
.
superclass
)
}
private
boolean
isPublicApi
(
CtMethod
method
)
{
return
Modifier
.
isPublic
(
method
.
modifiers
)
||
Modifier
.
isProtected
(
method
.
modifiers
)
}
private
List
<
String
>
filterChangesToReport
(
CtClass
c
,
Set
<
CtMethod
>
methods
)
{
return
methods
.
findAll
{
isFirstPublicClassInHierarchy
(
it
,
c
)
}*.
longName
.
sort
()
}
private
boolean
declaredInInternalClass
(
CtMethod
method
)
{
return
isInternal
(
method
.
declaringClass
)
}
private
boolean
isFirstPublicClassInHierarchy
(
CtMethod
method
,
CtClass
c
)
{
List
<
CtClass
>
classesContainingMethod
=
[]
CtClass
current
=
c
while
(
current
!=
null
)
{
if
(
containsMethod
(
current
,
method
))
{
classesContainingMethod
.
add
(
current
)
}
else
{
break
}
current
=
current
.
getSuperclass
()
}
for
(
int
i
=
classesContainingMethod
.
size
()
-
1
;
i
>
0
;
--
i
)
{
current
=
classesContainingMethod
.
get
(
i
)
if
(!
isInternal
(
current
))
{
// there's another public super class which contains target method
// it would be reported somewhere else
return
false
}
}
// I'm the top public class which contains target method
return
true
}
private
boolean
containsMethod
(
CtClass
c
,
CtMethod
method
)
{
// TODO signature contains return type
// but return type can be overridden
return
collectAllPublicApiMethods
(
c
).
any
{
it
.
signature
==
method
.
signature
}
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/NewIncubatingAPIRule.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
japicmp.model.JApiCompatibility
;
import
japicmp.model.JApiClass
;
import
japicmp.model.JApiField
;
import
japicmp.model.JApiHasAnnotations
;
import
japicmp.model.JApiMethod
;
import
me.champeau.gradle.japicmp.report.Violation
;
import
java.util.Map
;
public
class
NewIncubatingAPIRule
extends
AbstractGradleViolationRule
{
public
NewIncubatingAPIRule
(
Map
<
String
,
String
>
acceptedViolations
)
{
super
(
acceptedViolations
);
}
@Override
public
Violation
maybeViolation
(
final
JApiCompatibility
member
)
{
if
(
member
instanceof
JApiMethod
||
member
instanceof
JApiField
||
member
instanceof
JApiClass
)
{
if
(!
isIncubatingOrDeprecated
((
JApiHasAnnotations
)
member
))
{
return
null
;
}
if
(
member
instanceof
JApiMethod
&&
isOverride
((
JApiMethod
)
member
))
{
return
null
;
}
return
Violation
.
info
(
member
,
"New public API in "
+
getCurrentVersion
()
+
" (@Incubating)"
);
}
return
null
;
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/SinceAnnotationMissingRule.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
com.github.javaparser.JavaParser
;
import
com.github.javaparser.ast.body.AnnotationDeclaration
;
import
com.github.javaparser.ast.body.BodyDeclaration
;
import
com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
;
import
com.github.javaparser.ast.body.ConstructorDeclaration
;
import
com.github.javaparser.ast.body.EnumConstantDeclaration
;
import
com.github.javaparser.ast.body.EnumDeclaration
;
import
com.github.javaparser.ast.body.FieldDeclaration
;
import
com.github.javaparser.ast.body.MethodDeclaration
;
import
com.github.javaparser.ast.visitor.GenericVisitorAdapter
;
import
japicmp.model.JApiClass
;
import
japicmp.model.JApiCompatibility
;
import
japicmp.model.JApiConstructor
;
import
japicmp.model.JApiField
;
import
japicmp.model.JApiMethod
;
import
me.champeau.gradle.japicmp.report.Violation
;
import
java.util.Map
;
public
class
SinceAnnotationMissingRule
extends
AbstractGradleViolationRule
{
public
SinceAnnotationMissingRule
(
Map
<
String
,
String
>
acceptedViolations
)
{
super
(
acceptedViolations
);
}
@Override
public
Violation
maybeViolation
(
final
JApiCompatibility
member
)
{
String
className
=
null
;
GenericVisitorAdapter
<
Object
,
Void
>
visitor
=
null
;
if
(
member
instanceof
JApiMethod
&&
!
isOverride
((
JApiMethod
)
member
))
{
final
JApiMethod
method
=
(
JApiMethod
)
member
;
if
(
isDeprecated
(
method
))
{
return
null
;
}
className
=
method
.
getjApiClass
().
getFullyQualifiedName
();
visitor
=
new
GenericVisitorAdapter
<
Object
,
Void
>()
{
@Override
public
Object
visit
(
ClassOrInterfaceDeclaration
classDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
classDeclaration
.
getName
(),
toSimpleName
(
method
.
getjApiClass
().
getFullyQualifiedName
()),
classDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
classDeclaration
,
arg
);
}
@Override
public
Object
visit
(
AnnotationDeclaration
annotationDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
annotationDeclaration
.
getName
(),
toSimpleName
(
method
.
getjApiClass
().
getFullyQualifiedName
()),
annotationDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
annotationDeclaration
,
arg
);
}
@Override
public
Object
visit
(
EnumDeclaration
enumDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
enumDeclaration
.
getName
(),
toSimpleName
(
method
.
getjApiClass
().
getFullyQualifiedName
()),
enumDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
enumDeclaration
,
arg
);
}
@Override
public
Object
visit
(
MethodDeclaration
methodDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
methodDeclaration
.
getName
(),
method
.
getName
(),
methodDeclaration
))
{
return
new
Object
();
}
return
null
;
}
};
}
else
if
(
member
instanceof
JApiField
)
{
final
JApiField
field
=
(
JApiField
)
member
;
if
(
isDeprecated
(
field
))
{
return
null
;
}
className
=
field
.
getjApiClass
().
getFullyQualifiedName
();
visitor
=
new
GenericVisitorAdapter
<
Object
,
Void
>()
{
@Override
public
Object
visit
(
ClassOrInterfaceDeclaration
classDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
classDeclaration
.
getName
(),
toSimpleName
(
field
.
getjApiClass
().
getFullyQualifiedName
()),
classDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
classDeclaration
,
arg
);
}
@Override
public
Object
visit
(
AnnotationDeclaration
annotationDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
annotationDeclaration
.
getName
(),
toSimpleName
(
field
.
getjApiClass
().
getFullyQualifiedName
()),
annotationDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
annotationDeclaration
,
arg
);
}
@Override
public
Object
visit
(
EnumDeclaration
enumDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
enumDeclaration
.
getName
(),
toSimpleName
(
field
.
getjApiClass
().
getFullyQualifiedName
()),
enumDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
enumDeclaration
,
arg
);
}
@Override
public
Object
visit
(
FieldDeclaration
fieldDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
fieldDeclaration
.
getVariables
().
get
(
0
).
getId
().
getName
(),
field
.
getName
(),
fieldDeclaration
))
{
return
new
Object
();
}
return
null
;
}
@Override
public
Object
visit
(
EnumConstantDeclaration
enumConstantDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
enumConstantDeclaration
.
getName
(),
field
.
getName
(),
enumConstantDeclaration
))
{
return
new
Object
();
}
return
null
;
}
};
}
else
if
(
member
instanceof
JApiConstructor
)
{
final
JApiConstructor
constructor
=
(
JApiConstructor
)
member
;
if
(
isDeprecated
(
constructor
))
{
return
null
;
}
className
=
constructor
.
getjApiClass
().
getFullyQualifiedName
();
visitor
=
new
GenericVisitorAdapter
<
Object
,
Void
>()
{
@Override
public
Object
visit
(
ConstructorDeclaration
constructorDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
constructorDeclaration
.
getName
(),
toSimpleName
(
constructor
.
getjApiClass
().
getFullyQualifiedName
()),
constructorDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
constructorDeclaration
,
arg
);
}
@Override
public
Object
visit
(
ClassOrInterfaceDeclaration
classDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
classDeclaration
.
getName
(),
toSimpleName
(
constructor
.
getjApiClass
().
getFullyQualifiedName
()),
classDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
classDeclaration
,
arg
);
}
@Override
public
Object
visit
(
AnnotationDeclaration
annotationDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
annotationDeclaration
.
getName
(),
toSimpleName
(
constructor
.
getjApiClass
().
getFullyQualifiedName
()),
annotationDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
annotationDeclaration
,
arg
);
}
@Override
public
Object
visit
(
EnumDeclaration
enumDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
enumDeclaration
.
getName
(),
toSimpleName
(
constructor
.
getjApiClass
().
getFullyQualifiedName
()),
enumDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
enumDeclaration
,
arg
);
}
@Override
public
Object
visit
(
FieldDeclaration
fieldDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
fieldDeclaration
.
getVariables
().
get
(
0
).
getId
().
getName
(),
constructor
.
getName
(),
fieldDeclaration
))
{
return
new
Object
();
}
return
null
;
}
@Override
public
Object
visit
(
EnumConstantDeclaration
enumConstantDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
enumConstantDeclaration
.
getName
(),
constructor
.
getName
(),
enumConstantDeclaration
))
{
return
new
Object
();
}
return
null
;
}
};
}
else
if
(
member
instanceof
JApiClass
)
{
final
JApiClass
clazz
=
(
JApiClass
)
member
;
if
(
isDeprecated
(
clazz
))
{
return
null
;
}
className
=
clazz
.
getFullyQualifiedName
();
visitor
=
new
GenericVisitorAdapter
<
Object
,
Void
>()
{
@Override
public
Object
visit
(
ClassOrInterfaceDeclaration
classDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
classDeclaration
.
getName
(),
toSimpleName
(
clazz
.
getFullyQualifiedName
()),
classDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
classDeclaration
,
arg
);
}
@Override
public
Object
visit
(
AnnotationDeclaration
annotationDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
annotationDeclaration
.
getName
(),
toSimpleName
(
clazz
.
getFullyQualifiedName
()),
annotationDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
annotationDeclaration
,
arg
);
}
@Override
public
Object
visit
(
EnumDeclaration
enumDeclaration
,
Void
arg
)
{
if
(
matchesNameAndContainsAnnotation
(
enumDeclaration
.
getName
(),
toSimpleName
(
clazz
.
getFullyQualifiedName
()),
enumDeclaration
))
{
return
new
Object
();
}
return
super
.
visit
(
enumDeclaration
,
arg
);
}
};
}
if
(
className
==
null
)
{
return
null
;
}
try
{
Object
result
=
JavaParser
.
parse
(
sourceFileFor
(
className
)).
accept
(
visitor
,
null
);
if
(
result
==
null
)
{
return
acceptOrReject
(
member
,
Violation
.
error
(
member
,
"Is not annotated with @since "
+
getCurrentVersion
()));
}
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
return
null
;
}
private
String
toSimpleName
(
String
className
)
{
String
[]
bits
=
className
.
split
(
"\\."
);
return
bits
[
bits
.
length
-
1
];
}
private
boolean
matchesNameAndContainsAnnotation
(
String
name1
,
String
name2
,
BodyDeclaration
declaration
)
{
name2
=
name2
.
replaceAll
(
".*\\$"
,
""
);
//strip outer class names
return
name1
.
equals
(
name2
)
&&
declaration
.
getComment
()
!=
null
&&
declaration
.
getComment
().
getContent
().
contains
(
"@since "
+
getCurrentVersion
());
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/SinceAnnotationMissingRuleAPISourceFoldersSetup.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
me.champeau.gradle.japicmp.report.SetupRule
;
import
me.champeau.gradle.japicmp.report.ViolationCheckContext
;
import
java.util.Map
;
import
java.util.Set
;
public
class
SinceAnnotationMissingRuleAPISourceFoldersSetup
implements
SetupRule
{
private
final
Set
<
String
>
apiSourceFolders
;
public
SinceAnnotationMissingRuleAPISourceFoldersSetup
(
Map
<
String
,
String
>
sourceFolders
)
{
this
.
apiSourceFolders
=
sourceFolders
.
keySet
();
}
@SuppressWarnings
(
"unchecked"
)
public
void
execute
(
ViolationCheckContext
context
)
{
Map
<
String
,
Object
>
userData
=
(
Map
<
String
,
Object
>)
context
.
getUserData
();
userData
.
put
(
"apiSourceFolders"
,
apiSourceFolders
);
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/rules/SinceAnnotationMissingRuleCurrentGradleVersionSetup.java
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.rules
;
import
me.champeau.gradle.japicmp.report.SetupRule
;
import
me.champeau.gradle.japicmp.report.ViolationCheckContext
;
import
java.util.Map
;
public
class
SinceAnnotationMissingRuleCurrentGradleVersionSetup
implements
SetupRule
{
private
final
String
currentVersion
;
public
SinceAnnotationMissingRuleCurrentGradleVersionSetup
(
Map
<
String
,
String
>
currentVersion
)
{
this
.
currentVersion
=
currentVersion
.
get
(
"currentVersion"
);
}
@SuppressWarnings
(
"unchecked"
)
public
void
execute
(
ViolationCheckContext
context
)
{
Map
<
String
,
Object
>
userData
=
(
Map
<
String
,
Object
>)
context
.
getUserData
();
userData
.
put
(
"currentVersion"
,
currentVersion
);
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/transforms/ExplodeZipAndFindJars.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.transforms
import
groovy.transform.CompileStatic
import
org.gradle.api.artifacts.transform.ArtifactTransform
import
java.util.zip.ZipEntry
import
java.util.zip.ZipInputStream
import
java.nio.file.Files
@CompileStatic
class
ExplodeZipAndFindJars
extends
ArtifactTransform
{
@Override
List
<
File
>
transform
(
final
File
file
)
{
List
<
File
>
result
=
[]
if
(
outputDirectory
.
exists
()
&&
outputDirectory
.
listFiles
().
length
==
0
)
{
File
gradleJars
=
new
File
(
outputDirectory
,
"gradle-jars"
)
File
dependencies
=
new
File
(
outputDirectory
,
"gradle-dependencies"
)
gradleJars
.
mkdir
()
dependencies
.
mkdir
()
result
<<
gradleJars
result
<<
dependencies
ZipInputStream
zin
=
new
ZipInputStream
(
file
.
newInputStream
())
ZipEntry
zipEntry
while
(
zipEntry
=
zin
.
nextEntry
)
{
String
shortName
=
zipEntry
.
name
if
(
shortName
.
contains
(
'/'
))
{
shortName
=
shortName
.
substring
(
shortName
.
lastIndexOf
(
'/'
)
+
1
)
}
if
(
shortName
.
endsWith
(
'.jar'
))
{
def
outputDir
=
shortName
.
startsWith
(
'gradle-'
)
?
gradleJars
:
dependencies
def
out
=
new
File
(
outputDir
,
shortName
)
Files
.
copy
(
zin
,
out
.
toPath
())
zin
.
closeEntry
()
}
}
}
result
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleClasspath.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.transforms
import
org.gradle.api.artifacts.transform.ArtifactTransform
import
javax.inject.Inject
import
groovy.transform.CompileStatic
@CompileStatic
class
FindGradleClasspath
extends
ArtifactTransform
{
@Inject
FindGradleClasspath
()
{
}
@Override
List
<
File
>
transform
(
final
File
file
)
{
if
(
file
.
name
==
'gradle-dependencies'
)
{
(
file
.
listFiles
()
as
List
<
File
>).
sort
{
it
.
name
}
}
else
{
[]
}
}
}
buildSrc/src/main/groovy/org/gradle/binarycompatibility/transforms/FindGradleJar.groovy
0 → 100644
View file @
1f2273f0
/*
* Copyright 2017 the original author or authors.
*
* 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
org.gradle.binarycompatibility.transforms
import
org.gradle.api.artifacts.transform.ArtifactTransform
import
javax.inject.Inject
import
groovy.transform.CompileStatic
@CompileStatic
class
FindGradleJar
extends
ArtifactTransform
{
private
final
String
target
@Inject
FindGradleJar
(
String
target
)
{
this
.
target
=
target
}
@Override
List
<
File
>
transform
(
final
File
file
)
{
if
(
file
.
name
==
'gradle-jars'
)
{
(
file
.
listFiles
().
findAll
{
it
.
name
.
startsWith
(
"gradle-${target}-"
)
}
as
List
<
File
>).
sort
{
it
.
name
}
}
else
{
[]
}
}
}
Prev
1
2
3
4
5
…
50
Next