package org.shedlang.compiler.sourcefiles; import org.shedlang.compiler.parser.TokenType; import org.shedlang.compiler.parser.Tokeniser; import org.shedlang.compiler.types.NamespaceName; import org.zwobble.sourcetext.SourceText; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Optional; public class SourceFiles { private SourceFiles() { } public static List collectSourceFiles( Path sourceRoot ) throws IOException { var sourceFiles = new ArrayList(); Files.walkFileTree(sourceRoot, new SimpleFileVisitor() { @Override public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) { var namespaceName = relativeSourcePathToNamespaceName( sourceRoot.relativize(file) ); if (namespaceName.isPresent()) { var sourceFile = new SourceFile(file, namespaceName.get()); sourceFiles.add(sourceFile); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory( Path dir, IOException exc ) { return FileVisitResult.CONTINUE; } }); sourceFiles.sort(Comparator.comparing(x -> x.path(), Comparator.naturalOrder())); return sourceFiles; } private static Optional relativeSourcePathToNamespaceName( Path relativeSourcePath ) { var fileName = relativeSourcePath.getFileName().toString(); var shedSuffix = ".shed"; if (!fileName.endsWith(shedSuffix)) { return Optional.empty(); } var namespaceNameParts = new ArrayList(); for (var i = 0; i < relativeSourcePath.getNameCount() - 1; i++) { namespaceNameParts.add(relativeSourcePath.getName(i).toString()); } namespaceNameParts.add(fileName.substring(0, fileName.length() - shedSuffix.length())); for (var part : namespaceNameParts) { var tokens = Tokeniser.tokenise(SourceText.fromString("", part)); if (!( tokens.peek().tokenType() == TokenType.IDENTIFIER && tokens.peek(1).tokenType() == TokenType.END )) { return Optional.empty(); } } return Optional.of(new NamespaceName(namespaceNameParts)); } }