aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/shedlang/compiler/sourcefiles/SourceFiles.java
blob: c239fce8bc8fea146a3b8b77b25c27fb16400b77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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<SourceFile> collectSourceFiles(
        Path sourceRoot
    ) throws IOException {
        var sourceFiles = new ArrayList<SourceFile>();

        Files.walkFileTree(sourceRoot, new SimpleFileVisitor<Path>() {
            @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<NamespaceName> relativeSourcePathToNamespaceName(
        Path relativeSourcePath
    ) {
        var fileName = relativeSourcePath.getFileName().toString();
        var shedSuffix = ".shed";
        if (!fileName.endsWith(shedSuffix)) {
            return Optional.empty();
        }
        var namespaceNameParts = new ArrayList<String>();

        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("<string>", part));
            if (!(
                tokens.peek().tokenType() == TokenType.IDENTIFIER &&
                    tokens.peek(1).tokenType() == TokenType.END
            )) {
                return Optional.empty();
            }
        }

        return Optional.of(new NamespaceName(namespaceNameParts));
    }
}