Skip to content

Commit f6a87ae

Browse files
committed
Refactored japicc.gradle to work for modules
1 parent e6201a0 commit f6a87ae

File tree

1 file changed

+158
-150
lines changed

1 file changed

+158
-150
lines changed

Diff for: gradle/japicc.gradle

+158-150
Original file line numberDiff line numberDiff line change
@@ -1,192 +1,195 @@
11
task japicc {
22
group 'verification'
3-
description 'Checks for binary and source incompatibility.'
43

5-
def japiccVersion = '2.4'
6-
def workingDir = new File(project.buildDir, 'japicc')
7-
def executable = new File(workingDir, 'japi-compliance-checker-' + japiccVersion + '/japi-compliance-checker.pl')
8-
9-
def mavenRepo = "${project.repositories.mavenCentral().url}"
10-
11-
def lastSemVer = project.prevVersion == null ? lastSemVer() : project.prevVersion
12-
def shadedName = project.name + '-' + project.shadedAppendix
13-
def lastJar = new File(workingDir, project.name + '-' + lastSemVer + '.jar')
14-
def lastShadedJar = new File(workingDir, shadedName + '-' + lastSemVer + '.jar')
4+
ext {
5+
japiccVersion = '2.4'
6+
workingDir = new File(project.buildDir, 'japicc')
7+
executable = new File(workingDir, 'japi-compliance-checker-' + japiccVersion + '/japi-compliance-checker.pl')
8+
}
9+
}
10+
project.tasks.check.dependsOn(japicc)
1511

16-
def nonImplFile = new File(workingDir, 'non-impl')
12+
if (rootProject.tasks.findByName('japiccDownload') == null) {
13+
rootProject.tasks.create('japiccDownload') {
14+
group 'japicc'
15+
description 'Download Java API Compliance Checker'
1716

18-
def reportDir = new File(workingDir, 'compat_reports')
19-
def versions = lastSemVer + '_to_' + project.version
20-
def report = new File(new File(new File(reportDir, project.name), versions), 'compat_report.html')
21-
def shadedReport = new File(new File(new File(reportDir, shadedName), versions), 'compat_report.html')
17+
outputs.files japicc.executable
2218

23-
inputs.files jar, shadowJar
24-
outputs.files report, shadedReport
19+
File archive = new File(japicc.workingDir, 'japi-compliance-checker-' + japicc.japiccVersion + '.zip')
2520

26-
doFirst {
27-
description 'Check if last semantic version is available'
28-
println(description)
21+
doLast {
22+
archive.parentFile.mkdirs()
23+
if (!archive.exists()) {
24+
new URL('https://github.com/lvc/japi-compliance-checker/archive/' + japicc.japiccVersion + '.zip')
25+
.withInputStream { i -> archive.withOutputStream { it << i } }
26+
}
27+
}
2928

30-
if (project.version == lastSemVer) {
31-
throw new StopExecutionException('No last semantic version available')
29+
doLast {
30+
copy {
31+
from zipTree(archive)
32+
into japicc.workingDir
33+
}
3234
}
3335
}
36+
}
3437

35-
doLast {
38+
if (rootProject.tasks.findByName('japiccNonImpl') == null) {
39+
rootProject.tasks.create('japiccNonImpl') {
40+
group 'japicc'
3641
description 'List non impl interfaces'
37-
println(description)
38-
39-
nonImplFile.delete()
40-
nonImplFile.createNewFile()
41-
42-
sourceSets.main.java.visit { FileTreeElement f ->
43-
if (f.file.isFile()) {
44-
def packageName = f.relativePath.parent.pathString.replace('/', '.').replace('\\', '.')
45-
46-
def content = f.file.getText("UTF-8")
47-
content = content.replaceAll('//.*\n', ' ') // remove line comments
48-
content = content.replaceAll('\n', ' ') // remove new lines
49-
content = content.replaceAll('/\\*.*?\\*/', ' ') // remove multi line comments
50-
content = content.replaceAll(' +', ' ') // remove unnecessary spaces
51-
52-
def index = 0
53-
def classNames = []
54-
while (true) {
55-
def start = content.indexOf(' interface ', index)
56-
if (start == -1) break
57-
58-
def sub = content.substring(0, start)
59-
def level = sub.count('{') - sub.count('}')
60-
while (level < classNames.size()) {
61-
classNames.remove(classNames.size() - 1)
62-
}
6342

64-
start += ' interface '.length()
65-
def end = content.indexOf('{', start)
66-
if (end == -1) break
67-
68-
def interfaceDef = content.substring(start, end)
69-
def className = interfaceDef.split('[ <{]', 2)[0]
70-
classNames.add(className)
71-
72-
def annotationIndex = content.indexOf('@DoNotImplement', index)
73-
if (annotationIndex == -1) break
74-
75-
if (annotationIndex < start) {
76-
def qualifiedName = packageName + "." + classNames.join('.')
77-
78-
def rest = interfaceDef.substring(className.length()).trim()
79-
if (rest.startsWith('<')) {
80-
rest = rest.replaceAll('extends [^ <,]+', '') // remove all extends ...
81-
rest = rest.replaceAll('@.*? ', '') // remove all annotations
82-
def generics = '<'
83-
def nesting = 0
84-
for (def c : rest.chars) {
85-
if (c == '<') {
86-
nesting++
87-
} else if (c == '>') {
88-
nesting--
89-
} else if (nesting == 1) {
90-
generics += c
91-
} else if (nesting == 0) {
92-
break
43+
ext {
44+
nonImplFile = new File(japicc.workingDir, 'non-impl')
45+
}
46+
47+
inputs.files sourceSets.main.java
48+
outputs.files nonImplFile
49+
50+
doLast {
51+
nonImplFile.delete()
52+
nonImplFile.parentFile.mkdirs()
53+
nonImplFile.createNewFile()
54+
55+
sourceSets.main.java.visit { FileTreeElement f ->
56+
if (f.file.isFile()) {
57+
def packageName = f.relativePath.parent.pathString.replace('/', '.').replace('\\', '.')
58+
59+
def content = f.file.getText("UTF-8")
60+
content = content.replaceAll('//.*\n', ' ') // remove line comments
61+
content = content.replaceAll('\n', ' ') // remove new lines
62+
content = content.replaceAll('/\\*.*?\\*/', ' ') // remove multi line comments
63+
content = content.replaceAll(' +', ' ') // remove unnecessary spaces
64+
65+
def index = 0
66+
def classNames = []
67+
while (true) {
68+
def start = content.indexOf(' interface ', index)
69+
if (start == -1) break
70+
71+
def sub = content.substring(0, start)
72+
def level = sub.count('{') - sub.count('}')
73+
while (level < classNames.size()) {
74+
classNames.remove(classNames.size() - 1)
75+
}
76+
77+
start += ' interface '.length()
78+
def end = content.indexOf('{', start)
79+
if (end == -1) break
80+
81+
def interfaceDef = content.substring(start, end)
82+
def className = interfaceDef.split('[ <{]', 2)[0]
83+
classNames.add(className)
84+
85+
def annotationIndex = content.indexOf('@DoNotImplement', index)
86+
if (annotationIndex == -1) break
87+
88+
if (annotationIndex < start) {
89+
def qualifiedName = packageName + "." + classNames.join('.')
90+
91+
def rest = interfaceDef.substring(className.length()).trim()
92+
if (rest.startsWith('<')) {
93+
rest = rest.replaceAll('extends [^ <,]+', '') // remove all extends ...
94+
rest = rest.replaceAll('@.*? ', '') // remove all annotations
95+
def generics = '<'
96+
def nesting = 0
97+
for (def c : rest.chars) {
98+
if (c == '<') {
99+
nesting++
100+
} else if (c == '>') {
101+
nesting--
102+
} else if (nesting == 1) {
103+
generics += c
104+
} else if (nesting == 0) {
105+
break
106+
}
93107
}
108+
generics += '>'
109+
generics = generics.replace(' ', '')
110+
qualifiedName += generics
94111
}
95-
generics += '>'
96-
generics = generics.replace(' ', '')
97-
qualifiedName += generics
112+
113+
nonImplFile.append(qualifiedName + '\n')
98114
}
99115

100-
nonImplFile.append(qualifiedName + '\n')
116+
index = end + 1
101117
}
102-
103-
index = end + 1
104118
}
105119
}
106120
}
107121
}
122+
}
108123

109-
doLast {
110-
description 'Download Java API Compliance Checker'
111-
println(description)
124+
def addCheck(Jar jarTask) {
125+
String archiveBaseName = jarTask.archiveBaseName.get()
126+
String archiveAppendix = jarTask.archiveAppendix.getOrElse('')
127+
String taskName = 'japiccCheck' + archiveAppendix.capitalize()
112128

113-
def archive = new File(workingDir, 'japi-compliance-checker-' + japiccVersion + '.zip')
114-
archive.parentFile.mkdirs()
115-
if (!archive.exists()) {
116-
new URL('https://github.com/lvc/japi-compliance-checker/archive/' + japiccVersion + '.zip')
117-
.withInputStream { i -> archive.withOutputStream { it << i } }
129+
def task = project.tasks.create(taskName) {
118130

119-
copy {
120-
from zipTree(archive)
121-
into workingDir
122-
}
131+
group 'japicc'
132+
description 'Checks for binary and source incompatibility.'
133+
dependsOn rootProject.tasks.japiccDownload, rootProject.tasks.japiccNonImpl
134+
135+
File taskDir = new File(japicc.workingDir, taskName)
136+
String archiveName = archiveBaseName
137+
if (archiveAppendix == '-') {
138+
archiveName += '-' + archiveAppendix
123139
}
124-
}
125140

126-
doLast {
127-
description 'Download last version'
128-
println(description)
141+
String lastSemVer = project.prevVersion == null ? lastSemVer() : project.prevVersion
142+
String lastJarName = archiveName + '-' + lastSemVer + '.jar'
143+
File lastJar = new File(taskDir, lastJarName)
129144

130-
lastJar.parentFile.mkdirs()
131-
if (!lastJar.exists()) {
132-
String path = project.group.replace('.', '/')
133-
path += '/' + project.name + '/' + lastSemVer + '/'
134-
path += project.name + '-' + lastSemVer + '.jar'
135-
new URL(mavenRepo + path).withInputStream { i -> lastJar.withOutputStream { it << i } }
136-
}
137-
}
145+
File reportDir = new File(taskDir, 'compat_reports')
146+
File report = new File(new File(reportDir, lastSemVer + '_to_' + project.version), 'compat_report.html')
138147

139-
doLast {
140-
description 'Download last shaded version'
141-
println(description)
148+
inputs.files jarTask
149+
outputs.files report
142150

143-
lastShadedJar.parentFile.mkdirs()
144-
if (!lastShadedJar.exists()) {
145-
String path = project.group.replace('.', '/')
146-
path += '/' + shadedName + '/' + lastSemVer + '/'
147-
path += shadedName + '-' + lastSemVer + '.jar'
148-
new URL(mavenRepo + path).withInputStream { i -> lastShadedJar.withOutputStream { it << i } }
149-
}
150-
}
151+
doFirst {
152+
description 'Check if last semantic version is available'
153+
println(description)
151154

152-
doLast {
153-
description 'Check binary and source compatibility for last version'
154-
println(description)
155+
if (project.version == lastSemVer) {
156+
throw new StopExecutionException('No last semantic version available')
157+
}
158+
}
155159

156-
def command = ['perl', executable.getPath(), '-lib', project.name,
157-
'-skip-internal-packages', 'com.hivemq.client.internal',
158-
'-non-impl', nonImplFile.getPath(),
159-
'-check-annotations', '-s',
160-
lastJar.getPath(), jar.archiveFile.get().getAsFile().getPath()]
160+
doLast {
161+
description 'Download last version'
162+
println(description)
161163

162-
def process = new ProcessBuilder(command).directory(workingDir).start()
163-
def returnCode = process.waitFor()
164-
if (returnCode != 0) {
165-
throw new GradleException('Binary or source incompatibilities, code ' + returnCode)
164+
lastJar.parentFile.mkdirs()
165+
if (!lastJar.exists()) {
166+
String path = project.group.replace('.', '/') + '/' + archiveName + '/' + lastSemVer + '/' + lastJarName
167+
new URL(project.repositories.mavenCentral().url.toString() + path)
168+
.withInputStream { i -> lastJar.withOutputStream { it << i } }
169+
}
166170
}
167-
}
168171

169-
doLast {
170-
description 'Check binary and source compatibility for last shaded version'
171-
println(description)
172-
173-
def command = ['perl', executable.getPath(), '-lib', shadedName,
174-
'-skip-internal-packages', 'com.hivemq.client.internal',
175-
'-skip-internal-packages', 'com.hivemq.shaded',
176-
'-non-impl', nonImplFile.getPath(),
177-
'-check-annotations', '-s',
178-
lastShadedJar.getPath(), shadowJar.archiveFile.get().getAsFile().getPath()]
179-
180-
def process = new ProcessBuilder(command).directory(workingDir).start()
181-
def returnCode = process.waitFor()
182-
if (returnCode != 0) {
183-
throw new GradleException('Binary or source incompatibilities in shaded, code ' + returnCode)
172+
doLast {
173+
description 'Check binary and source compatibility for last version'
174+
println(description)
175+
176+
def command = ['perl', japicc.executable.getPath(), '-lib', archiveName,
177+
'-skip-internal-packages', 'com.hivemq.client.internal',
178+
'-skip-internal-packages', 'com.hivemq.shaded',
179+
'-non-impl', japiccNonImpl.nonImplFile.getPath(),
180+
'-check-annotations', '-s',
181+
lastJar.getPath(), jarTask.archiveFile.get().getAsFile().getPath()]
182+
183+
Process process = new ProcessBuilder(command).directory(taskDir).start()
184+
int returnCode = process.waitFor()
185+
if (returnCode != 0) {
186+
throw new GradleException('Binary or source incompatibilities, code ' + returnCode)
187+
}
184188
}
185189
}
190+
project.tasks.japicc.dependsOn(task)
186191
}
187192

188-
project.tasks.check.dependsOn(japicc)
189-
190193
String lastSemVer() {
191194
String version = project.version
192195
def split = version.split('-')[0].split('\\.')
@@ -200,3 +203,8 @@ String lastSemVer() {
200203
}
201204
return major + '.' + minor + '.' + patch
202205
}
206+
207+
addCheck(project.tasks.jar)
208+
if (project.plugins.hasPlugin('com.github.johnrengelman.shadow')) {
209+
addCheck(project.tasks.shadowJar)
210+
}

0 commit comments

Comments
 (0)