// Path: src/main/java/de/skuzzle/enforcer/restrictimports/parser/ImportStatementParser.java
// public interface ImportStatementParser {
//     /**
//      * Constructs a default instance of the parser which uses the provided charset.
//      *
//      * @param charset The charset to use.
//      * @return The parser instance.
//      */
//     static ImportStatementParser forCharset(Charset charset) {
//         return new ImportStatementParserImpl(new SkipCommentsLineSupplier(charset));
//     }
// 
//     /**
//      * Parses the given source file using the given {@link LanguageSupport} implementation
//      * to recognize import statements.
//      *
//      * @param sourceFilePath The path of the file to parse.
//      * @return The parsed file.
//      */
//     ParsedFile parse(Path sourceFilePath);
// }
// 
// Path: src/main/java/de/skuzzle/enforcer/restrictimports/parser/ParsedFile.java
// public final class ParsedFile {
// 
//     private final Path path;
//     private final String declaredPackage;
//     private final String fqcn;
//     private final Collection<ImportStatement> imports;
// 
//     public ParsedFile(Path path, String declaredPackage, String fqcn, Collection<ImportStatement> imports) {
//         this.path = path;
//         this.declaredPackage = declaredPackage;
//         this.fqcn = fqcn;
//         this.imports = imports;
//     }
// 
//     public Path getPath() {
//         return path;
//     }
// 
//     public Collection<ImportStatement> getImports() {
//         return imports;
//     }
// 
//     public String getFqcn() {
//         return fqcn;
//     }
// 
//     @Override
//     public String toString() {
//         return StringRepresentation.ofInstance(this)
//                 .add("path", path)
//                 .add("declaredPackage", declaredPackage)
//                 .add("fqcn", fqcn)
//                 .add("imports", imports)
//                 .toString();
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(path, declaredPackage, fqcn, imports);
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         return obj == this || obj instanceof ParsedFile
//                 && Objects.equals(path, ((ParsedFile) obj).path)
//                 && Objects.equals(declaredPackage, ((ParsedFile) obj).declaredPackage)
//                 && Objects.equals(fqcn, ((ParsedFile) obj).fqcn)
//                 && Objects.equals(imports, ((ParsedFile) obj).imports);
//     }
// 
// }
// 
// Path: src/main/java/de/skuzzle/enforcer/restrictimports/parser/lang/LanguageSupport.java
// public interface LanguageSupport {
// 
//     /**
//      * Returns the {@link LanguageSupport} implementation for the given file.
//      *
//      * @param path The path to a file.
//      * @return The {@link LanguageSupport} implementation or an empty optional if none was
//      *         found.
//      */
//     static LanguageSupport getLanguageSupport(Path path) {
//         final String extension = FileExtension.fromPath(path);
//         return SupportedLanguageHolder.getLanguageSupport(extension)
//                 .orElseThrow(() -> new IllegalArgumentException(String.format(
//                         "Could not find a LanguageSupport implementation for normalized file extension: '%s' (%s)",
//                         extension, path)));
//     }
// 
//     /**
//      * Determines whether there exists a {@link LanguageSupport} implementation for the
//      * given path.
//      *
//      * @param path The path to a file.
//      * @return Whether such implementation exists.
//      * @since 1.1.0
//      */
//     static boolean isLanguageSupported(Path path) {
//         final Path filename = path.getFileName();
//         return !Files.isDirectory(path)
//                 && SupportedLanguageHolder.isLanguageSupported(FileExtension.fromPath(filename));
//     }
// 
//     /**
//      * The set of supported file extensions. Extensions returned here are case insensitive
//      * and may or may not start with a '.' (dot).
//      *
//      * @return The set of file extensions.
//      */
//     Set<String> getSupportedFileExtensions();
// 
//     /**
//      * Parses the given line and returns the declared package
//      *
//      * @param line Line in the source file
//      * @return The package declared
//      */
//     Optional<String> parsePackage(String line);
// 
//     /**
//      * Extract the package names that this import statement represents. As some languages
//      * allow to specify multiple imports in a single line, this method returns a list.
//      * <p>
//      * e.g. import java.util.List; The above should return java.util.List in a Java source
//      * file.
//      *
//      * @param importLine Line in the source file
//      * @param lineNumber The line number of the import.
//      * @return Fully qualified package name that this import represents
//      */
//     List<ImportStatement> parseImport(String importLine, int lineNumber);
// }


import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.skuzzle.enforcer.restrictimports.parser.ImportStatementParser;
import de.skuzzle.enforcer.restrictimports.parser.ParsedFile;
import de.skuzzle.enforcer.restrictimports.parser.lang.LanguageSupport;
package de.skuzzle.enforcer.restrictimports.analyze;




final class SourceTreeAnalyzerImpl implements SourceTreeAnalyzer {

    private static final Logger LOGGER = LoggerFactory.getLogger(SourceTreeAnalyzerImpl.class);

    private final ImportAnalyzer importAnalyzer;
    private final Predicate<Path> supportedFileTypes;

    SourceTreeAnalyzerImpl() {
        this.importAnalyzer = new ImportAnalyzer();
// Path: src/main/java/de/skuzzle/enforcer/restrictimports/parser/ImportStatementParser.java
// public interface ImportStatementParser {
//     /**
//      * Constructs a default instance of the parser which uses the provided charset.
//      *
//      * @param charset The charset to use.
//      * @return The parser instance.
//      */
//     static ImportStatementParser forCharset(Charset charset) {
//         return new ImportStatementParserImpl(new SkipCommentsLineSupplier(charset));
//     }
// 
//     /**
//      * Parses the given source file using the given {@link LanguageSupport} implementation
//      * to recognize import statements.
//      *
//      * @param sourceFilePath The path of the file to parse.
//      * @return The parsed file.
//      */
//     ParsedFile parse(Path sourceFilePath);
// }
// 
// Path: src/main/java/de/skuzzle/enforcer/restrictimports/parser/ParsedFile.java
// public final class ParsedFile {
// 
//     private final Path path;
//     private final String declaredPackage;
//     private final String fqcn;
//     private final Collection<ImportStatement> imports;
// 
//     public ParsedFile(Path path, String declaredPackage, String fqcn, Collection<ImportStatement> imports) {
//         this.path = path;
//         this.declaredPackage = declaredPackage;
//         this.fqcn = fqcn;
//         this.imports = imports;
//     }
// 
//     public Path getPath() {
//         return path;
//     }
// 
//     public Collection<ImportStatement> getImports() {
//         return imports;
//     }
// 
//     public String getFqcn() {
//         return fqcn;
//     }
// 
//     @Override
//     public String toString() {
//         return StringRepresentation.ofInstance(this)
//                 .add("path", path)
//                 .add("declaredPackage", declaredPackage)
//                 .add("fqcn", fqcn)
//                 .add("imports", imports)
//                 .toString();
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(path, declaredPackage, fqcn, imports);
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         return obj == this || obj instanceof ParsedFile
//                 && Objects.equals(path, ((ParsedFile) obj).path)
//                 && Objects.equals(declaredPackage, ((ParsedFile) obj).declaredPackage)
//                 && Objects.equals(fqcn, ((ParsedFile) obj).fqcn)
//                 && Objects.equals(imports, ((ParsedFile) obj).imports);
//     }
// 
// }
// 
// Path: src/main/java/de/skuzzle/enforcer/restrictimports/parser/lang/LanguageSupport.java
// public interface LanguageSupport {
// 
//     /**
//      * Returns the {@link LanguageSupport} implementation for the given file.
//      *
//      * @param path The path to a file.
//      * @return The {@link LanguageSupport} implementation or an empty optional if none was
//      *         found.
//      */
//     static LanguageSupport getLanguageSupport(Path path) {
//         final String extension = FileExtension.fromPath(path);
//         return SupportedLanguageHolder.getLanguageSupport(extension)
//                 .orElseThrow(() -> new IllegalArgumentException(String.format(
//                         "Could not find a LanguageSupport implementation for normalized file extension: '%s' (%s)",
//                         extension, path)));
//     }
// 
//     /**
//      * Determines whether there exists a {@link LanguageSupport} implementation for the
//      * given path.
//      *
//      * @param path The path to a file.
//      * @return Whether such implementation exists.
//      * @since 1.1.0
//      */
//     static boolean isLanguageSupported(Path path) {
//         final Path filename = path.getFileName();
//         return !Files.isDirectory(path)
//                 && SupportedLanguageHolder.isLanguageSupported(FileExtension.fromPath(filename));
//     }
// 
//     /**
//      * The set of supported file extensions. Extensions returned here are case insensitive
//      * and may or may not start with a '.' (dot).
//      *
//      * @return The set of file extensions.
//      */
//     Set<String> getSupportedFileExtensions();
// 
//     /**
//      * Parses the given line and returns the declared package
//      *
//      * @param line Line in the source file
//      * @return The package declared
//      */
//     Optional<String> parsePackage(String line);
// 
//     /**
//      * Extract the package names that this import statement represents. As some languages
//      * allow to specify multiple imports in a single line, this method returns a list.
//      * <p>
//      * e.g. import java.util.List; The above should return java.util.List in a Java source
//      * file.
//      *
//      * @param importLine Line in the source file
//      * @param lineNumber The line number of the import.
//      * @return Fully qualified package name that this import represents
//      */
//     List<ImportStatement> parseImport(String importLine, int lineNumber);
// }


// Path: src/main/java/de/skuzzle/enforcer/restrictimports/analyze/SourceTreeAnalyzerImpl.java
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.skuzzle.enforcer.restrictimports.parser.ImportStatementParser;
import de.skuzzle.enforcer.restrictimports.parser.ParsedFile;
import de.skuzzle.enforcer.restrictimports.parser.lang.LanguageSupport;

package de.skuzzle.enforcer.restrictimports.analyze;




final class SourceTreeAnalyzerImpl implements SourceTreeAnalyzer {

    private static final Logger LOGGER = LoggerFactory.getLogger(SourceTreeAnalyzerImpl.class);

    private final ImportAnalyzer importAnalyzer;
    private final Predicate<Path> supportedFileTypes;

    SourceTreeAnalyzerImpl() {
        this.importAnalyzer = new ImportAnalyzer();
        this.supportedFileTypes = LanguageSupport::isLanguageSupported;