Commits

David Carr  committed 82b1806

snapshot work in progress

This may not all be working, but I've been working far too long without committing.

  • Participants
  • Parent commits eda5cbd

Comments (0)

Files changed (9)

File build.gradle

+apply plugin: 'groovy'
+
+dependencies {
+    compile gradleApi()
+    groovy localGroovy()
+}

File src/main/groovy/us/carrclan/david/gradle/taglist/TagDefinition.groovy

+package us.carrclan.david.gradle.taglist
+
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+class TagDefinition implements Serializable {
+    private static final long serialVersionUID = 1L
+
+    String name
+    Set<Pattern> patterns = []
+
+    /**
+     * Attempts to find a matching pattern in the specified line.  Returns the starting index of the match if one was
+     * found, or -1 if no match was found.
+     */
+    int findMatch(String line) {
+        for (Pattern pattern : patterns) {
+            println "Processing pattern ${pattern}"
+            Matcher matcher = pattern.matcher(line)
+            if (matcher.find()) {
+                return matcher.start()
+            }
+        }
+        return -1
+    }
+}

File src/main/groovy/us/carrclan/david/gradle/taglist/TagLocation.groovy

+package us.carrclan.david.gradle.taglist
+
+class TagLocation {
+    File file
+    int lineNum
+    int columnNum
+    String lineContent
+
+    String getMatch() {
+        return lineContent.substring(columnNum-1)
+    }
+
+    @Override
+    String toString() {
+        return "[${file.path}:${lineNum}:${columnNum}]: ${match}"
+    }
+}

File src/main/groovy/us/carrclan/david/gradle/taglist/TaglistPlugin.groovy

+package us.carrclan.david.gradle.taglist
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.file.FileVisitDetails
+import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.api.plugins.ReportingBasePlugin
+import org.gradle.api.reporting.Report
+import org.gradle.api.reporting.ReportingExtension
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.diagnostics.ProjectReportTask
+
+class TaglistPlugin implements Plugin<Project> {
+    @Override
+    void apply(Project project) {
+        project.plugins.apply(ReportingBasePlugin)
+        TaglistPluginExtension extension = project.extensions.create("taglist", TaglistPluginExtension)
+        extension.conventionMapping.with {
+            sourceSets = { [] }
+            reportsDir = { project.extensions.getByType(ReportingExtension).file("taglist") }
+            tags = { [] }
+        }
+        project.plugins.withType(JavaBasePlugin) {
+            extension.conventionMapping.sourceSets = { project.sourceSets }
+        }
+        project.tasks.withType(TaglistReport) { task ->
+            println "moo"
+            task.conventionMapping.with {
+                println "quack"
+//                sourceSets = { extension.sourceSets }
+                tags = { extension.tags }
+//                htmlFile = { new File(extension.reportsDir, "taglist.html") }
+            }
+            task.source = { extension.sourceSets.collect {it.allSource} as Object[] }
+            task.reports.all { Report report ->
+                report.conventionMapping.with {
+                    enabled = { report.name == "txt" }
+                    destination = { new File(extension.reportsDir, "taglist.${report.name}") }
+                }
+            }
+        }
+        TaglistReport task = project.tasks.add("taglistReport", TaglistReport)
+        task.with {
+            description = "Generates a report about your tags."
+        }
+        project.tasks.matching {it.name == "projectReport"}.all {it.dependsOn(task)}
+    }
+}

File src/main/groovy/us/carrclan/david/gradle/taglist/TaglistPluginExtension.groovy

+package us.carrclan.david.gradle.taglist
+
+import org.gradle.api.tasks.SourceSet
+
+class TaglistPluginExtension {
+    Collection<SourceSet> sourceSets
+    File reportsDir
+    List<TagDefinition> tags
+}

File src/main/groovy/us/carrclan/david/gradle/taglist/TaglistReport.groovy

+package us.carrclan.david.gradle.taglist
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.FileCollection
+import org.gradle.api.file.FileVisitDetails
+import org.gradle.api.internal.ConventionTask
+import org.gradle.api.reporting.Reporting
+import org.gradle.api.reporting.SingleFileReport
+import org.gradle.api.reporting.internal.TaskReportContainer
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Nested
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.SkipWhenEmpty
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.SourceTask
+import org.gradle.api.tasks.TaskAction
+import org.gradle.internal.reflect.Instantiator
+
+import javax.inject.Inject
+
+class TaglistReport extends SourceTask { //implements Reporting<TaglistReports> {
+//    @OutputFile
+//    File htmlFile
+    @Input
+    List<TagDefinition> tags
+//    @SkipWhenEmpty
+//    @InputFiles
+//    FileCollection files
+//    @Input
+//    Collection<SourceSet> sourceSets
+
+    @Nested
+    TaglistReports reports = new TaglistReports(this)
+
+
+
+    @TaskAction
+    void run() {
+        Map<TagDefinition, Set<TagLocation>> results = findTagMatches()
+        outputReports(results)
+    }
+
+    private void outputReports(Map<TagDefinition, Set<TagLocation>> results) {
+        printResults(results)
+        if (reports.text.enabled) {
+            outputText(results)
+        }
+    }
+
+    private void outputText(Map<TagDefinition, Set<TagLocation>> results) {
+        reports.text.destination.withPrintWriter { PrintWriter writer ->
+            writer.printf()
+        }
+    }
+
+    private void printResults(Map<TagDefinition, Set<TagLocation>> results) {
+        for (TagDefinition tagDef : getTags()) {
+            Set<TagLocation> locations = results[tagDef]
+            println "${tagDef.name}: ${locations.size()}"
+            for (TagLocation location : locations) {
+                println "  ${location}"
+            }
+        }
+    }
+
+    private Map<TagDefinition, Set<TagLocation>> findTagMatches() {
+        Map<TagDefinition, Set<TagLocation>> results = [:]
+        for (TagDefinition tag : getTags()) {
+            results.put(tag, new LinkedHashSet<TagLocation>())
+        }
+        for (file in getSource()) {
+            processFile(file, results)
+        }
+        results
+    }
+
+    void processFile(File file, Map<TagDefinition, Set<TagLocation>> results) {
+        println "Processing file ${file}"
+        file.eachLine { String lineContent, int lineNum ->
+            processLine(file, lineContent, lineNum, results)
+        }
+    }
+
+    void processLine(File file, String lineContent, int lineNum, Map<TagDefinition, Set<TagLocation>> results) {
+        println "Processing line ${lineContent}"
+        getTags().each { TagDefinition tagDef ->
+            processTag(file, lineContent, lineNum, tagDef, results)
+        }
+    }
+
+    void processTag(File file, String lineContent, int lineNum, TagDefinition tagDef, Map<TagDefinition, Set<TagLocation>> results) {
+        println "Processing tag ${tagDef.name}"
+        int columnIndex = tagDef.findMatch(lineContent)
+        if (columnIndex >= 0) {
+            results[tagDef].add(new TagLocation(file: file, lineNum: lineNum, columnNum: columnIndex+1, lineContent: lineContent))
+        }
+    }
+}

File src/main/groovy/us/carrclan/david/gradle/taglist/TaglistReports.groovy

+package us.carrclan.david.gradle.taglist
+
+import org.gradle.api.Task
+import org.gradle.api.reporting.SingleFileReport
+import org.gradle.api.reporting.internal.TaskGeneratedSingleFileReport
+import org.gradle.api.reporting.internal.TaskReportContainer
+
+class TaglistReports extends TaskReportContainer<SingleFileReport> {
+    TaglistReports(Task task) {
+        super(SingleFileReport, task)
+        add(TaskGeneratedSingleFileReport, "html", task)
+        add(TaskGeneratedSingleFileReport, "txt", task)
+        add(TaskGeneratedSingleFileReport, "xml", task)
+    }
+
+    SingleFileReport getHtml() {
+        return getByName("html")
+    }
+
+    SingleFileReport getText() {
+        return getByName("txt")
+    }
+
+    SingleFileReport getXml() {
+        return getByName("xml")
+    }
+}

File src/main/resources/META-INF/gradle-plugins/taglist.properties

+implementation-class=us.carrclan.david.gradle.taglist.TaglistPlugin

File src/test/groovy/us/carrclan/david/gradle/taglist/TaglistPluginTest.groovy

+package us.carrclan.david.gradle.taglist
+
+import org.gradle.api.Project
+import org.gradle.testfixtures.ProjectBuilder
+import org.junit.Before
+import org.junit.Test
+
+class TaglistPluginTest {
+    private Project project
+    private TaglistPlugin plugin
+
+    @Before
+    void setUp() {
+        project = ProjectBuilder.builder().build()
+        plugin = new TaglistPlugin()
+    }
+
+    @Test
+    void extensionShouldBeRegisteredOnApply() {
+        plugin.apply(project)
+        assert project.taglist instanceof TaglistPluginExtension
+        assert project.taglist.sourceSets == []
+        assert project.relativePath(project.taglist.reportsDir) == "build/reports/taglist"
+        assert project.taglist.tags == []
+    }
+
+    @Test
+    void sourceSetsShouldBeAddedToExtensionIfPresent() {
+        plugin.apply(project)
+        project.apply plugin: "java"
+        assert project.taglist.sourceSets.collect {it.name} == ["main", "test"]
+    }
+
+    @Test
+    void taskShouldBeRegisteredOnApply() {
+        plugin.apply(project)
+        createJavaSourceFile()
+        TaglistReport task = project.tasks.getByName("taglistReport")
+        assert task.source.collect {project.relativePath(it)} == []
+        assert task.tags == []
+        assert task.reports.text.enabled
+        assert !task.reports.html.enabled
+        assert !task.reports.xml.enabled
+        assert project.relativePath(task.reports.html.destination) == "build/reports/taglist/taglist.html"
+        assert project.relativePath(task.reports.text.destination) == "build/reports/taglist/taglist.txt"
+        assert project.relativePath(task.reports.xml.destination) == "build/reports/taglist/taglist.xml"
+        //assert project.relativePath(project.tasks.taglist.htmlFile) == "build/reports/taglist/taglist.html"
+    }
+
+    @Test
+    void extensionChangesAreCarriedOverToTask() {
+        plugin.apply(project)
+        project.apply plugin: "java"
+        createJavaSourceFile()
+        project.taglist.tags = [new TagDefinition(name: "Important", patterns: [~/XXX/, ~/FIXME/] as Set)]
+        project.taglist.reportsDir = project.file("build/taglist")
+        TaglistReport task = project.tasks.getByName("taglistReport")
+        assert task.source.collect {project.relativePath(it)} == ["src/main/java/User.java"]
+        assert task.tags.collect {it.name} == ["Important"]
+        assert project.relativePath(task.reports.html.destination) == "build/taglist/taglist.html"
+    }
+
+    @Test
+    void addsDependencyToProjectReportTaskWhenPresent() {
+        plugin.apply(project)
+        project.apply plugin: "project-report"
+        assert project.tasks.getByName("projectReport").dependsOn.find {it instanceof TaglistReport}
+    }
+
+    @Test
+    void skippedIfNoSourceFiles() {
+        plugin.apply(project)
+        project.taglist.tags = [new TagDefinition(name: "TODO", patterns: [~/TODO/])]
+        TaglistReport task = project.tasks.getByName("taglistReport")
+        task.execute()
+        assert task.state.skipped
+    }
+
+    @Test
+    void testReportGeneration() {
+        plugin.apply(project)
+        project.apply plugin: "java"
+        createJavaSourceFile()
+        project.taglist.tags = [new TagDefinition(name: "TODO", patterns: [~/TODO/])]
+        TaglistReport task = project.tasks.getByName("taglistReport")
+//        project.tasks.taglist.tags = [tag(new TagDefinition(name: "TODO", patterns: [~/TODO/])]
+//        assert project.tasks.taglist.sourceSets.collect {it.name} == ["main", "test"]
+        assert task.source.collect {project.relativePath(it)} == ["src/main/java/User.java"]
+        task.execute()
+        assert task.state.executed
+        // TODO: assertions
+    }
+
+    private void createJavaSourceFile() {
+        File file1 = project.file("src/main/java/User.java")
+        file1.parentFile.mkdirs()
+        file1.text = """
+        This is my file
+        TODO: do something
+        TODO: do something else
+        fin
+        """
+    }
+}