Browse Source

Parse build_project_name as `[][]string`

Damian Tarnawski 1 năm trước cách đây
mục cha
commit
f93779d425
2 tập tin đã thay đổi với 69 bổ sung54 xóa
  1. 32 18
      core/odin/parser/file_tags.odin
  2. 37 36
      tests/core/odin/test_file_tags.odin

+ 32 - 18
core/odin/parser/file_tags.odin

@@ -18,7 +18,7 @@ Build_Kind :: struct {
 }
 
 File_Tags :: struct {
-	build_project_name: []string,
+	build_project_name: [][]string,
 	build:              []Build_Kind,
 	private:            Private_Flag,
 	ignore:             bool,
@@ -48,7 +48,9 @@ get_build_arch_from_string :: proc(str: string) -> runtime.Odin_Arch_Type {
 }
 
 @require_results
-parse_file_tags :: proc(file: ast.File) -> (tags: File_Tags) {
+parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags: File_Tags) {
+	context.allocator = allocator
+
 	if file.docs == nil {
 		return
 	}
@@ -87,7 +89,10 @@ parse_file_tags :: proc(file: ast.File) -> (tags: File_Tags) {
 	build_kinds: [dynamic]Build_Kind
 	defer shrink(&build_kinds)
 
-	build_project_names: [dynamic]string
+	build_project_name_strings: [dynamic]string
+	defer shrink(&build_project_name_strings)
+
+	build_project_names: [dynamic][]string
 	defer shrink(&build_project_names)
 
 	for comment in file.docs.list {
@@ -116,23 +121,32 @@ parse_file_tags :: proc(file: ast.File) -> (tags: File_Tags) {
 					tags.private = .Package
 				}
 			case "build-project-name":
-				values_loop: for {
-					skip_whitespace(text, &i)
-
-					name_start := i
-
-					switch next_char(text, &i) {
-					case 0, '\n':
-						i -= 1
-						break values_loop
-					case '!':
-						// include ! in the name
-					case:
-						i -= 1
+				groups_loop: for {
+					index_start := len(build_project_name_strings)
+
+					defer append(&build_project_names, build_project_name_strings[index_start:])
+
+					for {
+						skip_whitespace(text, &i)
+						name_start := i
+	
+						switch next_char(text, &i) {
+						case 0, '\n':
+							i -= 1
+							break groups_loop
+						case ',':
+							continue groups_loop
+						case '!':
+							// include ! in the name
+						case:
+							i -= 1
+						}
+	
+						scan_value(text, &i)
+						append(&build_project_name_strings, text[name_start:i])
 					}
 
-					scan_value(text, &i)
-					append(&build_project_names, text[name_start:i])
+					append(&build_project_names, build_project_name_strings[index_start:])
 				}
 			case "build":
 				kinds_loop: for {

+ 37 - 36
tests/core/odin/test_file_tags.odin

@@ -3,6 +3,7 @@ package test_core_odin_parser
 import "base:runtime"
 import "core:testing"
 import "core:slice"
+import "core:log"
 import "core:odin/ast"
 import "core:odin/parser"
 
@@ -60,12 +61,12 @@ package main
 			},
 		}, {// [4]
 			src = `
-//+build-project-name foo !bar
+//+build-project-name foo !bar, baz
 //+build js wasm32, js wasm64p32
 package main
 			`,
 			tags = {
-				build_project_name = {"foo", "!bar"},
+				build_project_name = {{"foo", "!bar"}, {"baz"}},
 				build = {
 					{
 						os = {.JS},
@@ -79,11 +80,9 @@ package main
 		},
 	}
 
-	expect :: proc(t: ^testing.T, ok: bool, name: string, i: int, expected, actual: $T, loc := #caller_location) {
-		testing.expectf(t, ok,
-			"[%d] expected %s:\n\e[0;32m%#v\e[0m, actual:\n\e[0;31m%#v\e[0m",
-			i, name, expected, actual, loc=loc
-		)
+	error_expected :: proc(name: string, i: int, expected, actual: $T, loc := #caller_location) {
+		log.errorf("[%d] expected %s:\n\e[0;32m%#v\e[0m, actual:\n\e[0;31m%#v\e[0m",
+		           i, name, expected, actual, location=loc)
 	}
 
 	for test_case, i in test_cases {
@@ -100,34 +99,36 @@ package main
 
 		tags := parser.parse_file_tags(file)
 
-		expect(t,
-			slice.equal(test_case.tags.build_project_name, tags.build_project_name),
-			"build_project_name", i, test_case.tags.build_project_name, tags.build_project_name,
-		)
-
-		expect(t,
-			slice.equal(test_case.tags.build, tags.build),
-			"build", i, test_case.tags.build, tags.build,
-		)
-
-		expect(t,
-			test_case.tags.private == tags.private,
-			"private", i, test_case.tags.private, tags.private,
-		)
-
-		expect(t,
-			test_case.tags.ignore == tags.ignore,
-			"ignore", i, test_case.tags.ignore, tags.ignore,
-		)
-
-		expect(t,
-			test_case.tags.lazy == tags.lazy,
-			"lazy", i, test_case.tags.lazy, tags.lazy,
-		)
-
-		expect(t,
-			test_case.tags.no_instrumentation == tags.no_instrumentation,
-			"no_instrumentation", i, test_case.tags.no_instrumentation, tags.no_instrumentation,
-		)
+
+		build_project_name_the_same: bool
+		check: if len(test_case.tags.build_project_name) == len(tags.build_project_name) {
+			for tag, i in test_case.tags.build_project_name {
+				slice.equal(tag, tags.build_project_name[i]) or_break check
+			}
+			build_project_name_the_same = true
+		}
+		if !build_project_name_the_same {
+			error_expected("build_project_name", i, test_case.tags.build_project_name, tags.build_project_name)
+		}
+
+		if !slice.equal(test_case.tags.build, tags.build) {
+			error_expected("build", i, test_case.tags.build, tags.build,)
+		}
+
+		if test_case.tags.private != tags.private {
+			error_expected("private", i, test_case.tags.private, tags.private)
+		}
+
+		if test_case.tags.ignore != tags.ignore {
+			error_expected("ignore", i, test_case.tags.ignore, tags.ignore)
+		}
+
+		if test_case.tags.lazy != tags.lazy {
+			error_expected("lazy", i, test_case.tags.lazy, tags.lazy)
+		}
+
+		if test_case.tags.no_instrumentation != tags.no_instrumentation {
+			error_expected("no_instrumentation", i, test_case.tags.no_instrumentation, tags.no_instrumentation)
+		}
 	}
 }