Skip to content

Commit

Permalink
Dependency.t have a list of directives
Browse files Browse the repository at this point in the history
  • Loading branch information
na4zagin3 committed Nov 8, 2020
1 parent 7c22888 commit 70b84e6
Showing 1 changed file with 85 additions and 97 deletions.
182 changes: 85 additions & 97 deletions src/satysfi/dependency.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ type directive =

type t = {
path: string;
imports: (Location.t * string) list;
requires: (Location.t * string) list;
directives: (Location.t * directive) list;
}
[@@deriving sexp]

Expand Down Expand Up @@ -80,225 +79,214 @@ let of_directives ~path ds =
range = Some (ColumnRange cr);
}
in
let accum acc = function
| cr, Import c ->
{ acc with imports = (loc cr, c) :: acc.imports; }
| cr, Require c ->
{ acc with requires = (loc cr, c) :: acc.requires; }
in
let empty = {
{
path = path;
imports = [];
requires = [];
} in
List.fold_left ~f:accum ~init:empty ds
directives = List.map ds ~f:(fun (cr, d) -> loc cr, d);
}

let parse_string ~path str =
let parse_string_saty ~path str =
parse_directives str
|> of_directives ~path

let parse_file_result path =
Result.try_with (fun () ->
In_channel.read_all path
)
|> Result.map ~f:(parse_string ~path)

let%expect_test "parse_string: empty" =
let%expect_test "parse_string_saty: empty" =
let path = "test.saty" in
parse_string ~path ""
parse_string_saty ~path ""
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty) (imports ()) (requires ())) |}]
((path test.saty) (directives ())) |}]

let%expect_test "parse_string: single import with crlf" =
let%expect_test "parse_string_saty: single import with crlf" =
let path = "test.saty" in
parse_string ~path "@import: imported/file1\r\n"
parse_string_saty ~path "@import: imported/file1\r\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 8))))))))
imported/file1)))
(requires ())) |}]
(Import imported/file1))))) |}]

let%expect_test "parse_string: single import with eol" =
let%expect_test "parse_string_saty: single import with eol" =
let path = "test.saty" in
parse_string ~path "@import: imported/file1\n"
parse_string_saty ~path "@import: imported/file1\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 8))))))))
imported/file1)))
(requires ())) |}]
(Import imported/file1))))) |}]

let%expect_test "parse_string: single import with eos" =
let%expect_test "parse_string_saty: single import with eos" =
let path = "test.saty" in
parse_string ~path "@import: imported/file1"
parse_string_saty ~path "@import: imported/file1"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 8))))))))
imported/file1)))
(requires ())) |}]
(Import imported/file1))))) |}]

let%expect_test "parse_string: single require" =
let%expect_test "parse_string_saty: single require" =
let path = "test.saty" in
parse_string ~path "@require: required/file1"
parse_string_saty ~path "@require: required/file1"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty) (imports ())
(requires
((path test.saty)
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
required/file1)))) |}]
(Require required/file1))))) |}]

let%expect_test "parse_string: imports and requires" =
let%expect_test "parse_string_saty: imports and requires" =
let path = "test.saty" in
parse_string ~path "@require: required/file1\n@import: imported/file1\n@require: required/file2\n@import: imported/file2\n"
parse_string_saty ~path "@require: required/file1\n@import: imported/file1\n@require: required/file2\n@import: imported/file2\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 3) (cnum 1))) (rend ((lnum 3) (cnum 9))))))))
imported/file2)
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
(Require required/file1))
(((path test.saty)
(range
((ColumnRange
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 9))))))))
imported/file1)))
(requires
((((path test.saty)
(Import imported/file1))
(((path test.saty)
(range
((ColumnRange
((rstart ((lnum 2) (cnum 1))) (rend ((lnum 2) (cnum 10))))))))
required/file2)
(Require required/file2))
(((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
required/file1)))) |}]
((rstart ((lnum 3) (cnum 1))) (rend ((lnum 3) (cnum 9))))))))
(Import imported/file2))))) |}]

let%expect_test "parse_string: conflicting names" =
let%expect_test "parse_string_saty: conflicting names" =
let path = "test.saty" in
parse_string ~path "@require: file1\n@import: file1\n"
parse_string_saty ~path "@require: file1\n@import: file1\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 9))))))))
file1)))
(requires
((((path test.saty)
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
(Require file1))
(((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
file1)))) |}]
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 9))))))))
(Import file1))))) |}]

let%expect_test "parse_string: % in package name" =
let%expect_test "parse_string_saty: % in package name" =
let path = "test.saty" in
parse_string ~path "@require: file1 % not a comment\n@import: file1 % not a comment\n"
parse_string_saty ~path "@require: file1 % not a comment\n@import: file1 % not a comment\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 9))))))))
"file1 % not a comment")))
(requires
((((path test.saty)
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
(Require "file1 % not a comment"))
(((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 9))))))))
"file1 % not a comment")))) |}]
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 9))))))))
(Import "file1 % not a comment"))))) |}]

let%expect_test "parse_string: comment lines" =
let%expect_test "parse_string_saty: comment lines" =
let path = "test.saty" in
parse_string ~path "% comment\n%\n"
parse_string_saty ~path "% comment\n%\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty) (imports ()) (requires ())) |}]
((path test.saty) (directives ())) |}]

let%expect_test "parse_string: comment lines followed by directives" =
let%expect_test "parse_string_saty: comment lines followed by directives" =
let path = "test.saty" in
parse_string ~path "% comment\n%\n@import: file\n"
parse_string_saty ~path "% comment\n%\n@import: file\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 2) (cnum 1))) (rend ((lnum 2) (cnum 9))))))))
file)))
(requires ())) |}]
(Import file))))) |}]

let%expect_test "parse_string: comment lines interleaved between directives" =
let%expect_test "parse_string_saty: comment lines interleaved between directives" =
let path = "test.saty" in
parse_string ~path "% comment\n@require: lib\n%\n@import: file\n"
parse_string_saty ~path "% comment\n@require: lib\n%\n@import: file\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 3) (cnum 1))) (rend ((lnum 3) (cnum 9))))))))
file)))
(requires
((((path test.saty)
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 10))))))))
(Require lib))
(((path test.saty)
(range
((ColumnRange
((rstart ((lnum 1) (cnum 1))) (rend ((lnum 1) (cnum 10))))))))
lib)))) |}]
((rstart ((lnum 3) (cnum 1))) (rend ((lnum 3) (cnum 9))))))))
(Import file))))) |}]

let%expect_test "parse_string: directives followed by declarations" =
let%expect_test "parse_string_saty: directives followed by declarations" =
let path = "test.saty" in
parse_string ~path "@import: file\nlet x = 1\n"
parse_string_saty ~path "@import: file\nlet x = 1\n"
|> [%sexp_of: t]
|> Sexp.output_hum Out_channel.stdout;
[%expect{|
((path test.saty)
(imports
(directives
((((path test.saty)
(range
((ColumnRange
((rstart ((lnum 0) (cnum 0))) (rend ((lnum 0) (cnum 8))))))))
file)))
(requires ())) |}]
(Import file))))) |}]

let referred_file_basenames ~package_root_dirs { path; imports; requires; }=
let parse_file_result path =
Result.try_with (fun () ->
In_channel.read_all path
)
|> Result.map ~f:(match FilePath.get_extension path with
| _ -> parse_string_saty ~path)

let referred_file_basenames ~package_root_dirs { path; directives; }=
let basedir = FilePath.dirname path in
List.map imports ~f:(fun (loc, p) -> loc, Import p, [FilePath.concat basedir p])
@ List.map requires ~f:(fun (loc, p) -> loc, Require p, List.map package_root_dirs ~f:(fun rd -> FilePath.concat rd p))
List.map directives ~f:(fun (loc, d) ->
match d with
| Import f ->
loc, d, [FilePath.concat basedir f]
| Require p ->
loc, d, List.map package_root_dirs ~f:(fun rd -> FilePath.concat rd p)
)

0 comments on commit 70b84e6

Please sign in to comment.