Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
439aae4
Fix Compatibility in LintService and LintGradleTask
Nouran-11 Jun 5, 2025
221078a
Merge branch 'nebula-plugins:main' into main
Nouran-11 Jun 16, 2025
85b579e
main
Nouran-11 Jun 16, 2025
1e6b04c
Merge remote-tracking branch 'origin/main'
Nouran-11 Jun 16, 2025
26c9a4e
Merge branch 'nebula-plugins:main' into main
Nouran-11 Jun 16, 2025
a500a1c
Add `ProjectInfo` and `ProjectTree` classes
Nouran-11 Jun 20, 2025
97c8efa
Integrate `ProjectTree` computation in `LintGradleTask`
Nouran-11 Jun 20, 2025
5206747
Add `getAllFiles` method and`AppliedFilesAstVisitor` constructor with…
Nouran-11 Jun 22, 2025
2e18e54
Conditionally Remove DependencyService for Model-Aware Rules
Nouran-11 Jun 22, 2025
3ca28be
Add Overloaded removeForProject Method and buildRules method with Sup…
Nouran-11 Jun 22, 2025
bd2837a
Integrate `ProjectInfo` into `GradleLintPatchAction`
Nouran-11 Jun 23, 2025
941e341
Integrate projectInfo and ProjectTree instead of project
Nouran-11 Jun 23, 2025
77995b6
Integrate projectInfo and ProjectTree instead of project
Nouran-11 Jun 23, 2025
fc1a292
Integrate projectInfo and ProjectTree instead of project
Nouran-11 Jun 23, 2025
a79b6cf
Merge remote-tracking branch 'origin/main' into fixing-cc-nebula
Nouran-11 Jun 24, 2025
5319a23
Merge remote-tracking branch 'upstream/main' into fixing-cc-nebula
Nouran-11 Jun 24, 2025
b46ff28
Overload for lintService.ruleSet
Nouran-11 Jun 24, 2025
94ece27
fix AppliedFilesAstVisitor
Nouran-11 Jun 24, 2025
580bb0c
Use `findByType()` instead of `getByType()`
Nouran-11 Jun 24, 2025
ed9bf8a
Integrate `ProjectInfo` into GradleLintPatchAction`
Nouran-11 Jun 25, 2025
8902d78
Fix `GradleLintPatchAction`
Nouran-11 Jun 25, 2025
db9e58e
Fix `GradleLintPatchActionSpec`
Nouran-11 Jun 25, 2025
40372e7
Fix `GradleLintPatchAction`
Nouran-11 Jun 25, 2025
3b64570
Integrate `ProjectInfo` into `GradleLintInfoBrokerAction`
Nouran-11 Jun 26, 2025
6e2776f
fix `GradleLintInfoBrokerAction`
Nouran-11 Jun 26, 2025
66fcc31
Move action creation to configuration time in FixGradleLintTask
Nouran-11 Jun 26, 2025
f9af7c4
Integrate `ProjectInfo` and `ProjectTree` into `GradleLintReportTask`
Nouran-11 Jun 26, 2025
c6046f8
Create GradleLintPatchAction at configuration time using ProjectInfo …
Nouran-11 Jun 26, 2025
0568d44
Make `ProjectInfo` and `ProjectTree` internal in GradleLintReportTask…
Nouran-11 Jun 26, 2025
5777258
Add try and catch of config cache compatibility
Nouran-11 Jun 30, 2025
37354cd
Trade serialization problems for potential execution problems
abstratt Jul 1, 2025
1c0c023
Add CompitabilityTest
Nouran-11 Jul 1, 2025
e1f2691
delete test
Nouran-11 Jul 2, 2025
0081973
SpaceAssignmentRule compatibility
Nouran-11 Jul 2, 2025
4312972
SpaceAssignmentRule compatibility
Nouran-11 Jul 3, 2025
653c6da
revert changes for SpaceAssignmentRule
Nouran-11 Jul 17, 2025
2354013
Merge pull request #3 from Nouran-11/fixing-cc-nebula
Nouran-11 Jul 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,31 +1,42 @@
package com.netflix.nebula.lint

import com.netflix.nebula.lint.plugin.ProjectInfo
import groovy.transform.Canonical
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.Task

@Canonical
class GradleLintInfoBrokerAction extends GradleLintViolationAction {
Project project
Plugin nebulaInfoBroker
ProjectInfo projectInfo


GradleLintInfoBrokerAction(Task task){
this.projectInfo = ProjectInfo.from(task)
task.project.getPlugins().withId('nebula.info-broker') { plugin ->
nebulaInfoBroker = plugin
}
}

@Override
void lintFinished(Collection<GradleViolation> violations) {
project.getPlugins().withId('nebula.info-broker') {
nebulaInfoBroker?.tap{
def reportItems = violations.collect { buildReportItem(it) }
it.addReport('gradleLintViolations', reportItems)
}
}

@Override
void lintFixesApplied(Collection<GradleViolation> violations) {
project.getPlugins().withId('nebula.info-broker') {
nebulaInfoBroker?.tap {
def reportItems = violations.findAll { !it.fixes.any { it.reasonForNotFixing } }
.collect { buildReportItem(it) }
it.addReport('fixedGradleLintViolations', reportItems)
}
}

LintReportItem buildReportItem(GradleViolation v) {
def buildFilePath = project.rootDir.toURI().relativize(v.file.toURI()).toString()
def buildFilePath = projectInfo.rootDir.toURI().relativize(v.file.toURI()).toString()
new LintReportItem(buildFilePath, v.rule.name, v.rule.getPriority() as String,
v.lineNumber ?: -1, v.sourceLine ?: 'unspecified', v.message ?: "")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.nebula.lint

import com.netflix.nebula.lint.plugin.ProjectInfo
import com.netflix.nebula.lint.plugin.UnexpectedLintRuleFailureException
import groovy.transform.Canonical
import org.apache.commons.lang.StringUtils
Expand All @@ -30,12 +31,22 @@ import static java.nio.file.Files.readSymbolicLink
@Canonical
class GradleLintPatchAction extends GradleLintViolationAction {
Project project
ProjectInfo projectInfo

GradleLintPatchAction(Project project) {
this.project = project

}

GradleLintPatchAction(ProjectInfo projectInfo) {
this.projectInfo = projectInfo
}

static final String PATCH_NAME = 'lint.patch'

@Override
void lintFinished(Collection<GradleViolation> violations) {
File buildDir = project.layout.buildDirectory.asFile.getOrElse(new File(project.projectDir, "build"))
File buildDir = projectInfo ? projectInfo.buildDirectory : project.layout.buildDirectory.asFile.getOrElse(new File(project.projectDir, "build"))
buildDir.mkdirs()
try {
def patch = patch(violations*.fixes.flatten() as List<GradleLintFix>)
Expand Down Expand Up @@ -252,7 +263,7 @@ Exception: ${e.getMessage()}
if (i > 0)
combinedPatch += '\n'

def relativePath = project.rootDir.toPath().relativize(file.toPath()).toString()
def relativePath = projectInfo? projectInfo.rootDir.toPath().relativize(file.toPath()).toString() : project.rootDir.toPath().relativize(file.toPath()).toString()
def diffHeader = """\
${diffHintsWithMargin(relativePath, patchType, fileMode)}
|--- ${patchType == Create ? '/dev/null' : 'a/' + relativePath}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@ import org.gradle.api.Project
*/
class AppliedFilesAstVisitor extends ClassCodeVisitorSupport {

Project project
ProjectInfo projectInfo

List<File> appliedFiles = new ArrayList()
Map<String, String> projectVariablesMapping

AppliedFilesAstVisitor(Project project) {
this.project = project
AppliedFilesAstVisitor(ProjectInfo projectInfo) {
this.projectInfo = projectInfo
projectVariablesMapping = [
"\$projectDir" : project.projectDir.toString(),
"\$project.projectDir" : project.projectDir.toString(),
"\$rootDir" : project.rootDir.toString(),
"\$project.rootDir" : project.rootDir.toString(),
"\$projectDir" : projectInfo.projectDir.toString(),
"\$project.projectDir" : projectInfo.projectDir.toString(),
"\$rootDir" : projectInfo.rootDir.toString(),
"\$project.rootDir" : projectInfo.rootDir.toString(),
]
}

Expand All @@ -32,9 +33,9 @@ class AppliedFilesAstVisitor extends ClassCodeVisitorSupport {
def projectVariable = projectVariablesMapping.find {from.contains(it.key) }
if (projectVariable) {
def absolutePath = from.replaceAll("\\$projectVariable.key", projectVariable.value)
appliedFiles.addAll(SourceCollector.getAllFiles(new File(absolutePath), project))
appliedFiles.addAll(SourceCollector.getAllFiles(new File(absolutePath), projectInfo))
} else {
appliedFiles.addAll(SourceCollector.getAllFiles(new File(project.projectDir, from), project))
appliedFiles.addAll(SourceCollector.getAllFiles(new File(projectInfo.projectDir, from), projectInfo))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import com.netflix.nebula.lint.StyledTextService
import org.eclipse.jgit.api.ApplyCommand
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Task
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
Expand All @@ -46,28 +48,44 @@ abstract class FixGradleLintTask extends DefaultTask implements VerificationTask
@Internal
GradleLintInfoBrokerAction infoBrokerAction

@Internal
GradleLintPatchAction patchAction

@Internal
abstract Property<ProjectTree> getProjectTree()

@Internal
ProjectInfo getProjectInfo() {
return projectTree.get().baseProject
}

FixGradleLintTask() {
infoBrokerAction = new GradleLintInfoBrokerAction(project)
projectTree.set(project.provider {ProjectTree.from(this) })
infoBrokerAction = new GradleLintInfoBrokerAction(this)
patchAction = new GradleLintPatchAction(getProjectInfo())
userDefinedListeners.convention([])
outputs.upToDateWhen { false }
group = 'lint'
try {
def method = Task.getMethod("notCompatibleWithConfigurationCache")
method.invoke(this)
} catch (NoSuchMethodException ignore) {
}
}

@TaskAction
void lintCorrections() {
//TODO: address Invocation of Task.project at execution time has been deprecated.
DeprecationLogger.whileDisabled {
def violations = new LintService().lint(project, false).violations
def violations = new LintService().lint(projectTree.get(), false).violations
.unique { v1, v2 -> v1.is(v2) ? 0 : 1 }

(userDefinedListeners.get() + infoBrokerAction + new GradleLintPatchAction(project)).each {
(userDefinedListeners.get() + infoBrokerAction + patchAction).each {
it.lintFinished(violations)
}

def patchFile = new File(project.layout.buildDirectory.asFile.get(), GradleLintPatchAction.PATCH_NAME)
def patchFile = new File(getProjectInfo().buildDirectory, GradleLintPatchAction.PATCH_NAME)
if (patchFile.exists()) {
new ApplyCommand(new NotNecessarilyGitRepository(project.projectDir)).setPatch(patchFile.newInputStream()).call()
new ApplyCommand(new NotNecessarilyGitRepository(projectInfo.projectDir)).setPatch(patchFile.newInputStream()).call()
}

(userDefinedListeners.get() + infoBrokerAction + consoleOutputAction()).each {
Expand Down Expand Up @@ -97,7 +115,7 @@ abstract class FixGradleLintTask extends DefaultTask implements VerificationTask
violations.groupBy { it.file }.each { buildFile, projectViolations ->

projectViolations.each { v ->
String buildFilePath = project.rootDir.toURI().relativize(v.file.toURI()).toString()
String buildFilePath = projectTree.get().baseProject.rootDir.toURI().relativize(v.file.toURI()).toString()
def unfixed = v.fixes.findAll { it.reasonForNotFixing != null }
if (v.fixes.empty) {
textOutput.withStyle(Yellow).text('needs fixing'.padRight(15))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ abstract class GradleLintReportTask extends DefaultTask implements VerificationT
@Internal
final NamedDomainObjectContainer<LintReport> reports

@Internal
abstract Property<ProjectInfo> getProjectInfo()

@Internal
abstract Property<ProjectTree> getProjectTree()

@Inject
GradleLintReportTask(ObjectFactory objects) {
projectName = objects.property(String).convention(project.name)
projectInfo.convention(projectTree.map {it.baseProject })
projectTree.set(project.provider { ProjectTree.from(this) })
projectName = objects.property(String).convention(projectInfo.get().name)
reportsDir = objects.directoryProperty()
reports =
objects.domainObjectContainer(
Expand Down Expand Up @@ -90,7 +98,7 @@ abstract class GradleLintReportTask extends DefaultTask implements VerificationT
DeprecationLogger.whileDisabled {
if (reports.any { it.required.isPresent() && it.required.get()}) {
def lintService = new LintService()
def results = lintService.lint(project, false)
def results = lintService.lint(projectTree.get(), false)
filterOnlyFixableViolations(results)
def violationCount = results.violations.size()
def textOutput = new StyledTextService(getServices())
Expand All @@ -101,7 +109,7 @@ abstract class GradleLintReportTask extends DefaultTask implements VerificationT

reports.each {
if(it.required.isPresent() && it.required.get()) {
it.write(new AnalysisContext(ruleSet: lintService.ruleSet(project)), results)
it.write(new AnalysisContext(ruleSet: lintService.ruleSet(projectTree.get())), results)
}
}

Expand Down Expand Up @@ -142,7 +150,7 @@ abstract class GradleLintReportTask extends DefaultTask implements VerificationT

void filterOnlyFixableViolations(Results results) {
if (reportOnlyFixableViolations.isPresent() && reportOnlyFixableViolations.get()) {
new GradleLintPatchAction(project).lintFinished(results.violations)
new GradleLintPatchAction(projectInfo.get()).lintFinished(results.violations)
List<Violation> toRemove = results.violations.findAll {
it.fixes.size() == 0 || it.fixes.any { it.reasonForNotFixing != null }
}
Expand Down
106 changes: 102 additions & 4 deletions src/main/groovy/com/netflix/nebula/lint/plugin/LintGradleTask.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@
*/
package com.netflix.nebula.lint.plugin

import com.google.common.annotations.VisibleForTesting
import com.netflix.nebula.lint.*
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction
import org.gradle.internal.deprecation.DeprecationLogger

import java.util.function.Supplier

import static com.netflix.nebula.lint.StyledTextService.Styling.*

abstract class LintGradleTask extends DefaultTask {
Expand All @@ -45,9 +48,27 @@ abstract class LintGradleTask extends DefaultTask {
@Input
abstract Property<File> getProjectRootDir()

@Input
abstract Property<ProjectTree> getProjectTree()

@Input
abstract Property<ProjectInfo> getProjectInfo()

@Internal
GradleLintInfoBrokerAction infoBrokerAction

@Internal
GradleLintPatchAction patchAction


LintGradleTask() {
failOnWarning.convention(false)
onlyCriticalRules.convention(false)
projectTree.set(project.provider {ProjectTree.from(this) })
projectInfo.convention(projectTree.map(ProjectTree::getBaseProject))
projectRootDir.set(project.rootDir)
infoBrokerAction = new GradleLintInfoBrokerAction(this)
patchAction = new GradleLintPatchAction(getProjectInfo().get())
group = 'lint'
try {
def method = Task.getMethod("notCompatibleWithConfigurationCache")
Expand All @@ -58,12 +79,11 @@ abstract class LintGradleTask extends DefaultTask {

@TaskAction
void lint() {
//TODO: address Invocation of Task.project at execution time has been deprecated.
DeprecationLogger.whileDisabled {
def violations = new LintService().lint(project, onlyCriticalRules.get()).violations
def violations = new LintService().lint(projectTree.get(), onlyCriticalRules.get()).violations
.unique { v1, v2 -> v1.is(v2) ? 0 : 1 }

(getListeners() + new GradleLintPatchAction(project) + new GradleLintInfoBrokerAction(project) + consoleOutputAction).each {
(getListeners() + patchAction + infoBrokerAction + consoleOutputAction).each {
it.lintFinished(violations)
}
}
Expand Down Expand Up @@ -139,3 +159,81 @@ abstract class LintGradleTask extends DefaultTask {
}
}
}
/**
* A CC-compatible projection of project data.
*/
class ProjectInfo implements Serializable{
String name
String path
File rootDir
File buildFile
File projectDir
File buildDirectory
GradleLintExtension extension
Map<String, Object> properties
Supplier<Project> projectSupplier

static ProjectInfo from(Task task, Project subproject) {
String subprojectPath = subproject.path
return build(subproject, { task.project.project(subprojectPath) })
}

static ProjectInfo from(Task task) {
return build(task.project, task::getProject)
}

@VisibleForTesting
private static ProjectInfo build(Project project, Supplier<Project> projectSupplier) {
GradleLintExtension extension =
project.extensions.findByType(GradleLintExtension) ?:
project.rootProject.extensions.findByType(GradleLintExtension)
Map<String, Object> properties = [:]
if (project.hasProperty('gradleLint.rules')) {
properties['gradleLint.rules'] = project.property('gradleLint.rules')
}
if (project.hasProperty('gradleLint.excludedRules')) {
properties['gradleLint.excludedRules'] = project.property('gradleLint.excludedRules')
}

return new ProjectInfo(
name:project.name,
path:project.path,
rootDir:project.rootDir,
buildFile: project.buildFile,
projectDir:project.projectDir,
extension: extension,
properties: properties,
projectSupplier: projectSupplier,
buildDirectory : project.buildDir
)

}


}

class ProjectTree{
List<ProjectInfo> allProjects

ProjectTree(List<ProjectInfo> allProjects){
this.allProjects = allProjects
}

/**
* Returns the base project this tree was built from.
*/
ProjectInfo getBaseProject() {
return allProjects.head()
}

/**
* Build a project tree based on the given task's project.
*
* @return a project tree reflecting information and the structure of the given task's project
*/
static from(Task task) {
def baseProject = task.project
List<ProjectInfo> projectInfos = [ProjectInfo.from(task)] + baseProject.subprojects.collect { Project p -> ProjectInfo.from(task, p) }
return new ProjectTree(projectInfos)
}
}
Loading