All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.nebula.lint.rule.BuildFiles.groovy Maven / Gradle / Ivy

Go to download

Pluggable and configurable linter tool for identifying and reporting on patterns of misuse or deprecations in Gradle scripts

There is a newer version: 20.2.2
Show newest version
package com.netflix.nebula.lint.rule

import groovy.transform.CompileStatic

/**
 * This class provides transformation from multiple build files to one concatenated text which is used for applying
 * lint rules. We keep original mapping so we can get based on line number in concatenated text original line and file.
 */
@CompileStatic
class BuildFiles {

    private Map orderedFiles = new LinkedHashMap<>()

    BuildFiles(List allFiles) {
        int currentLinesTotal = 0
        allFiles.each { File buildFile ->
            int count = linesCount(buildFile)
            LineRange range = new LineRange(currentLinesTotal + 1, currentLinesTotal + count)
            currentLinesTotal += count
            orderedFiles.put(range, buildFile)
        }
    }

    private static int linesCount(File file) {
        /*
         Enhancement (JDK 16): The line terminator definition was changed in java.io.LineNumberReader
         More info: https://blogs.oracle.com/javamagazine/post/the-hidden-gems-in-java-16-and-java-17-from-streammapmulti-to-hexformat
        */
        if(System.getProperty("java.specification.version").isInteger() && System.getProperty("java.specification.version").toInteger() >= 16) {
           linesCountModernJdk(file)
        } else {
           linesCountOlderJdk(file)
        }
    }

    private static int linesCountModernJdk(File file) {
        boolean shouldAddOne = file.text.empty || file.text.endsWith("\n")
        file.withReader { reader ->
            LineNumberReader lineNumberReader = new LineNumberReader(reader)
            while (lineNumberReader.read() != -1) {}
            if(shouldAddOne) {
                lineNumberReader.getLineNumber() + 1
            } else {
                lineNumberReader.getLineNumber()
            }
        }
    }

    private static int linesCountOlderJdk(File file) {
        file.withReader { reader ->
            LineNumberReader lineNumberReader = new LineNumberReader(reader)
            while (lineNumberReader.read() != -1) {}
            lineNumberReader.getLineNumber() + 1
        }
    }

    String getText() {
        StringBuilder result = new StringBuilder()
        orderedFiles.each {
            result.append(it.value.text).append('\n')
        }
        result.toString()
    }

    Original original(Integer concatenatedFileLine) {
        if (concatenatedFileLine != null) {
            Map.Entry entry = orderedFiles.find { key, value ->
                key.within(concatenatedFileLine)
            }
            if (entry == null) {
                String ranges = orderedFiles
                        .collect { key, value -> "Lines $key.start - $key.end are $value.absolutePath"}
                        .join('\n')
                throw new IllegalArgumentException("Asked line in concatenated file was: $concatenatedFileLine" +
                        " but it wasn't found. Original project files were concatenated to following ranges:\n$ranges")
            }
            new Original(
                    file: entry.value,
                    line: concatenatedFileLine - (entry.key.start - 1)
            )
        } else {
            new Original(
                    file: orderedFiles.values().first(),
                    line: null as Integer
            )
        }
    }

    static class Original {
        File file
        Integer line
    }

    static private class LineRange {
        int start
        int end

        LineRange(int start, int end) {
            this.start = start
            this.end = end
        }

        boolean within(int line) {
            start <= line && line <= end
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy