Skip to content

Commit 77ac73b

Browse files
committed
Finish gradle plugin
1 parent 206d0a6 commit 77ac73b

File tree

4 files changed

+244
-68
lines changed

4 files changed

+244
-68
lines changed

src/cfgnet/plugins/.DS_Store

0 Bytes
Binary file not shown.

src/cfgnet/plugins/concept/gradle_plugin.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ def _process_method_call(self, tree, parent_node):
274274

275275
if not method_name:
276276
return
277+
278+
# --- Skip plugins DSL "id '...'" entries from the AST pass
279+
# They are already handled (with versions) by the text extractor in _extract_config_from_text.
280+
if getattr(parent_node, "name", None) == "plugins" and method_name == "id":
281+
return
277282

278283
# Check if this is a simple method call with a string argument
279284
string_arg = self._extract_first_string_argument(tree)
@@ -691,22 +696,26 @@ def pop_one():
691696

692697
# --- dependencies { } DSL
693698
if ctx == "dependencies":
694-
m = re_dep_decl.match(line)
695-
if m:
696-
conf = m.group(1)
697-
spec = m.group(2).strip()
698-
699-
# Prefer a quoted coordinate inside the spec
700-
quoted = re.findall(r"['\"]([^'\"]+)['\"]", spec)
701-
candidate = quoted[0] if quoted else spec
702-
703-
option_name, version = self._parse_artifact_coordinates(candidate)
704-
if version:
705-
# g:a:v -> option g:a, value v (no conf in key)
706-
self._add_option_value(node_stack[-1], option_name, version, str(lineno))
707-
else:
708-
# g:a (no version) -> option conf, value candidate
709-
self._add_option_value(node_stack[-1], conf, candidate, str(lineno))
699+
# ADD THIS GUARD:
700+
if line.endswith("{") or line == "{" or line == "}":
701+
pass
702+
else:
703+
m = re_dep_decl.match(line)
704+
if m:
705+
conf = m.group(1)
706+
spec = m.group(2).strip()
707+
708+
# Prefer a quoted coordinate inside the spec
709+
quoted = re.findall(r"['\"]([^'\"]+)['\"]", spec)
710+
candidate = quoted[0] if quoted else spec
711+
712+
option_name, version = self._parse_artifact_coordinates(candidate)
713+
if version:
714+
# g:a:v -> option g:a, value v (no conf in key)
715+
self._add_option_value(node_stack[-1], option_name, version, str(lineno))
716+
else:
717+
# g:a (no version) -> option conf, value candidate
718+
self._add_option_value(node_stack[-1], conf, candidate, str(lineno))
710719

711720
# --- generic "=" assignments (everywhere, under current block path)
712721
m_assign = re_assignment.match(line)

tests/cfgnet/plugins/concept/test_gradle_plugin.py

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,54 +80,110 @@ def test_parse_build_gradle(get_plugin):
8080
assert artifact.concept_name == "gradle"
8181

8282
nodes = artifact.get_nodes()
83-
assert len(nodes) > 0
8483

85-
# Check for specific extracted values
86-
group_node = next(filter(lambda x: x.id == make_id("build.gradle", "group", "com.example"), nodes), None)
87-
version_node = next(filter(lambda x: x.id == make_id("build.gradle", "version", "1.0.0"), nodes), None)
88-
source_compat_node = next(filter(lambda x: x.id == make_id("build.gradle", "sourceCompatibility", "11"), nodes), None)
89-
main_class_node = next(filter(lambda x: x.id == make_id("build.gradle", "application", "mainClass", "com.example.Main"), nodes), None)
84+
# Check for plugins (id as option, version as nested option, version number as value)
85+
# Structure: plugins -> plugin-id -> version -> version-number
86+
plugin_versions = next(
87+
filter(
88+
lambda x: x.id == make_id("build.gradle", "plugins", "com.github.ben-manes.versions", "version", "0.53.0"),
89+
nodes
90+
),
91+
None
92+
)
93+
plugin_spotbugs = next(
94+
filter(
95+
lambda x: x.id == make_id("build.gradle", "plugins", "com.github.spotbugs", "version", "6.4.8"),
96+
nodes
97+
),
98+
None
99+
)
100+
plugin_shadow = next(
101+
filter(
102+
lambda x: x.id == make_id("build.gradle", "plugins", "com.gradleup.shadow", "version", "9.3.1"),
103+
nodes
104+
),
105+
None
106+
)
107+
plugin_jmh = next(
108+
filter(
109+
lambda x: x.id == make_id("build.gradle", "plugins", "me.champeau.jmh", "version", "0.7.2"),
110+
nodes
111+
),
112+
None
113+
)
90114

91-
assert group_node is not None
92-
assert group_node.config_type == ConfigType.NAME
93-
assert version_node is not None
94-
assert version_node.config_type == ConfigType.VERSION_NUMBER
95-
assert source_compat_node is not None
96-
assert main_class_node is not None
115+
assert plugin_versions is not None, "Plugin 'com.github.ben-manes.versions' should be parsed"
116+
assert plugin_spotbugs is not None, "Plugin 'com.github.spotbugs' should be parsed"
117+
assert plugin_shadow is not None, "Plugin 'com.gradleup.shadow' should be parsed"
118+
assert plugin_jmh is not None, "Plugin 'me.champeau.jmh' should be parsed"
97119

98120
# Check for ext properties
99-
kotlin_version_node = next(filter(lambda x: x.id == make_id("build.gradle", "ext", "kotlinVersion", "1.8.0"), nodes), None)
100-
spring_version_node = next(filter(lambda x: x.id == make_id("build.gradle", "ext", "springVersion", "5.3.20"), nodes), None)
121+
github_project_name = next(filter(lambda x: x.id == make_id("build.gradle", "ext.githubProjectName", "spectator"), nodes), None)
122+
assert github_project_name is not None
101123

102-
assert kotlin_version_node is not None
103-
assert spring_version_node is not None
104-
105-
# Check for specific dependencies (groupId:artifactId as option, version as value)
106-
# Structure: dependencies -> org.springframework.boot:spring-boot-starter-web -> 2.7.0
107-
spring_boot_dep = next(
124+
# Check for dependencies
125+
# Structure: subprojects -> dependencies -> configuration-type -> dependency-name
126+
slf4j_dep = next(
108127
filter(
109-
lambda x: x.id == make_id("build.gradle", "dependencies", "org.springframework.boot:spring-boot-starter-web", "2.7.0"),
128+
lambda x: x.id == make_id("build.gradle", "subprojects", "dependencies", "implementation", "org.slf4j:slf4j-api"),
110129
nodes
111130
),
112131
None
113132
)
114133
junit_dep = next(
115134
filter(
116-
lambda x: x.id == make_id("build.gradle", "dependencies", "junit:junit", "4.13.2"),
135+
lambda x: x.id == make_id("build.gradle", "subprojects", "dependencies", "testImplementation", "org.junit.jupiter:junit-jupiter"),
136+
nodes
137+
),
138+
None
139+
)
140+
equalsverifier_dep = next(
141+
filter(
142+
lambda x: x.id == make_id("build.gradle", "subprojects", "dependencies", "testImplementation", "nl.jqno.equalsverifier:equalsverifier"),
117143
nodes
118144
),
119145
None
120146
)
121147

122-
assert spring_boot_dep is not None, "Spring Boot dependency should be parsed as groupId:artifactId"
123-
assert junit_dep is not None, "JUnit dependency should be parsed as groupId:artifactId"
124-
125-
# Check for ext properties
126-
kotlin_version_node = next(filter(lambda x: x.id == make_id("build.gradle", "ext", "kotlinVersion", "1.8.0"), nodes), None)
127-
spring_version_node = next(filter(lambda x: x.id == make_id("build.gradle", "ext", "springVersion", "5.3.20"), nodes), None)
128-
129-
assert kotlin_version_node is not None
130-
assert spring_version_node is not None
148+
assert slf4j_dep is not None, "SLF4J dependency should be parsed"
149+
assert junit_dep is not None, "JUnit Jupiter dependency should be parsed"
150+
assert equalsverifier_dep is not None, "EqualsVerifier dependency should be parsed"
151+
152+
# Check for jmh section options (all options should be parsed, not just the first one)
153+
jmh_version = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "jmh", "jmhVersion", "1.37"), nodes), None)
154+
jmh_warmup = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "jmh", "warmupIterations", "2"), nodes), None)
155+
jmh_iterations = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "jmh", "iterations", "5"), nodes), None)
156+
jmh_fork = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "jmh", "fork", "1"), nodes), None)
157+
jmh_includeTests = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "jmh", "includeTests", "false"), nodes), None)
158+
159+
assert jmh_version is not None, "jmh.jmhVersion should be parsed"
160+
assert jmh_warmup is not None, "jmh.warmupIterations should be parsed (not just first option)"
161+
assert jmh_iterations is not None, "jmh.iterations should be parsed"
162+
assert jmh_fork is not None, "jmh.fork should be parsed"
163+
assert jmh_includeTests is not None, "jmh.includeTests should be parsed"
164+
165+
# Check for checkstyle section options
166+
checkstyle_version = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "checkstyle", "toolVersion", "13.1.0"), nodes), None)
167+
checkstyle_ignoreFailures = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "checkstyle", "ignoreFailures", "false"), nodes), None)
168+
169+
assert checkstyle_version is not None, "checkstyle.toolVersion should be parsed"
170+
assert checkstyle_ignoreFailures is not None, "checkstyle.ignoreFailures should be parsed"
171+
172+
# Check for spotbugs section options
173+
spotbugs_version = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "spotbugs", "toolVersion", "4.9.8"), nodes), None)
174+
spotbugs_useJavaToolchains = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "spotbugs", "useJavaToolchains", "false"), nodes), None)
175+
spotbugs_ignoreFailures = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "spotbugs", "ignoreFailures", "false"), nodes), None)
176+
177+
assert spotbugs_version is not None, "spotbugs.toolVersion should be parsed"
178+
assert spotbugs_useJavaToolchains is not None, "spotbugs.useJavaToolchains should be parsed"
179+
assert spotbugs_ignoreFailures is not None, "spotbugs.ignoreFailures should be parsed"
180+
181+
# Check for pmd section options
182+
pmd_version = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "pmd", "toolVersion", "7.16.0"), nodes), None)
183+
pmd_ignoreFailures = next(filter(lambda x: x.id == make_id("build.gradle", "subprojects", "pmd", "ignoreFailures", "false"), nodes), None)
184+
185+
assert pmd_version is not None, "pmd.toolVersion should be parsed"
186+
assert pmd_ignoreFailures is not None, "pmd.ignoreFailures should be parsed"
131187

132188

133189
def test_parse_settings_gradle(get_plugin):

tests/files/build.gradle

Lines changed: 132 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,142 @@
11
plugins {
2-
id 'java'
3-
id 'application'
2+
id 'com.github.ben-manes.versions' version '0.53.0'
3+
id 'com.github.spotbugs' version '6.4.8' apply false
4+
id 'com.gradleup.shadow' version '9.3.1' apply false
5+
id 'me.champeau.jmh' version '0.7.2'
46
}
57

6-
group = 'com.example'
7-
version = '1.0.0'
8+
// Establish version and status
9+
ext.githubProjectName = 'spectator'
810

9-
sourceCompatibility = '11'
10-
targetCompatibility = '11'
11+
allprojects {
12+
apply plugin: 'project-report'
13+
apply plugin: 'me.champeau.jmh'
14+
apply plugin: 'com.github.ben-manes.versions'
1115

12-
repositories {
16+
// Needs to be here to avoid problems with JMH plugin
17+
repositories {
1318
mavenCentral()
19+
mavenLocal()
20+
}
1421
}
1522

16-
dependencies {
17-
implementation platform('org.apache.groovy:groovy-bom:5.+')
18-
implementation 'org.springframework.boot:spring-boot-starter-web:2.7.0'
19-
implementation 'org.apache.groovy:groovy-json'
20-
implementation ':simple-jar'
21-
testImplementation 'junit:junit:4.13.2'
22-
}
23+
subprojects {
24+
apply plugin: 'com.netflix.nebula.dependency-recommender'
25+
apply plugin: 'com.netflix.nebula.netflixoss'
26+
apply plugin: 'java-library'
2327

24-
application {
25-
mainClass = 'com.example.Main'
26-
}
28+
group = "com.netflix.${githubProjectName}"
2729

28-
ext {
29-
kotlinVersion = '1.8.0'
30-
springVersion = '5.3.20'
31-
}
30+
java {
31+
toolchain {
32+
languageVersion = JavaLanguageVersion.of(8)
33+
}
34+
}
35+
36+
tasks.withType(JavaCompile) {
37+
options.encoding = 'UTF-8'
38+
}
39+
40+
tasks {
41+
javadoc {
42+
options.addStringOption('Xdoclint:none', '-quiet')
43+
}
44+
}
45+
46+
javadoc {
47+
options {
48+
links = ['https://docs.oracle.com/javase/8/docs/api/']
49+
}
50+
}
51+
52+
dependencyRecommendations {
53+
propertiesFile file: new File(rootProject.projectDir, 'dependencies.properties')
54+
}
55+
56+
dependencies {
57+
implementation "org.slf4j:slf4j-api"
58+
testImplementation 'org.junit.jupiter:junit-jupiter'
59+
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
60+
testImplementation 'nl.jqno.equalsverifier:equalsverifier'
61+
jmh "org.slf4j:slf4j-simple"
62+
jmh "org.openjdk.jmh:jmh-core:1.37"
63+
jmh "org.openjdk.jmh:jmh-generator-annprocess:1.37"
64+
}
65+
66+
tasks.withType(Test) {
67+
useJUnitPlatform()
68+
}
69+
70+
[17, 21, 25].each { additionalJDK ->
71+
def additionalTestTask = tasks.register("testJDK$additionalJDK", Test) {
72+
description = "Runs tests against JDK $additionalJDK."
73+
group = 'verification'
74+
75+
testClassesDirs = sourceSets.test.output.classesDirs
76+
classpath = sourceSets.test.runtimeClasspath
77+
78+
javaLauncher = javaToolchains.launcherFor {
79+
languageVersion = JavaLanguageVersion.of(additionalJDK)
80+
}
81+
}
82+
check.dependsOn additionalTestTask
83+
}
84+
85+
jmh {
86+
jmhVersion = '1.37'
87+
warmupIterations = 2
88+
iterations = 5
89+
fork = 1
90+
//threads = 1
91+
profilers = ['stack', 'gc']
92+
includeTests = false
93+
duplicateClassesStrategy = DuplicatesStrategy.WARN
94+
includes = ['.*Ids.*']
95+
}
96+
97+
checkstyle {
98+
toolVersion = '13.1.0'
99+
ignoreFailures = false
100+
configFile = rootProject.file('codequality/checkstyle.xml')
101+
configDirectory = rootProject.file("codequality")
102+
sourceSets = [sourceSets.main]
103+
}
104+
105+
tasks.withType(Checkstyle) {
106+
// Use the JVM running Gradle (JDK 25) instead of the project toolchain (JDK 8)
107+
javaLauncher = javaToolchains.launcherFor {
108+
languageVersion = JavaLanguageVersion.of(25)
109+
}
110+
}
111+
112+
spotbugs {
113+
toolVersion = '4.9.8'
114+
useJavaToolchains = false
115+
excludeFilter = rootProject.file('codequality/findbugs-exclude.xml')
116+
ignoreFailures = false
117+
spotbugsMain.enabled = true
118+
spotbugsTest.enabled = false
119+
spotbugsJmh.enabled = false
120+
}
121+
spotbugsMain {
122+
reports {
123+
xml.enabled = false
124+
html.enabled = true
125+
}
126+
}
127+
128+
pmd {
129+
toolVersion = '7.16.0'
130+
ignoreFailures = false
131+
sourceSets = [sourceSets.main]
132+
ruleSets = []
133+
ruleSetFiles = rootProject.files("codequality/pmd.xml")
134+
}
135+
136+
tasks.withType(Pmd) {
137+
// Use the JVM running Gradle (JDK 17) instead of the project toolchain (JDK 8)
138+
javaLauncher = javaToolchains.launcherFor {
139+
languageVersion = JavaLanguageVersion.of(17)
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)