summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--lib/core/macros.nim7
-rw-r--r--tests/macros/texpectIdent1.nim18
-rw-r--r--tests/macros/texpectIdent2.nim24
4 files changed, 50 insertions, 1 deletions
diff --git a/changelog.md b/changelog.md
index 49567e929..44c654fd3 100644
--- a/changelog.md
+++ b/changelog.md
@@ -69,6 +69,7 @@
 - Added `minIndex`, `maxIndex` and `unzip` to the `sequtils` module.
 - Added `os.isRelativeTo` to tell whether a path is relative to another
 - Added `resetOutputFormatters` to `unittest`
+- Added `expectIdent` to the `macros` module.
 - Added `os.isValidFilename` that returns `true` if `filename` argument is valid for crossplatform use.
 
 - Added a `with` macro for easy function chaining that's available
@@ -95,7 +96,6 @@ echo f
 - Added a new module, `std / compilesettings` for querying the compiler about
   diverse configuration settings.
 
-
 ## Library changes
 
 - `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index cc20f1dac..57ce89c02 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -1433,6 +1433,13 @@ else:
     else:
       result = false
 
+proc expectIdent*(n: NimNode, name: string) {.compileTime, since: (1,1).} =
+  ## Check that ``eqIdent(n,name)`` holds true. If this is not the
+  ## case, compilation aborts with an error message. This is useful
+  ## for writing macros that check the AST that is passed to them.
+  if not eqIdent(n, name):
+    error("Expected identifier to be `" & name & "` here", n)
+
 proc hasArgOfName*(params: NimNode; name: string): bool {.compileTime.}=
   ## Search ``nnkFormalParams`` for an argument.
   expectKind(params, nnkFormalParams)
diff --git a/tests/macros/texpectIdent1.nim b/tests/macros/texpectIdent1.nim
new file mode 100644
index 000000000..26e52afb5
--- /dev/null
+++ b/tests/macros/texpectIdent1.nim
@@ -0,0 +1,18 @@
+discard """
+errormsg: "Expected identifier to be `foo` here"
+line: 18
+"""
+
+import macros
+
+macro testUntyped(arg: untyped): void =
+  arg.expectKind nnkStmtList
+  arg.expectLen 2
+  arg[0].expectKind nnkCall
+  arg[0][0].expectIdent "foo"  # must pass
+  arg[1].expectKind nnkCall
+  arg[1][0].expectIdent "foo"  # must fail
+
+testUntyped:
+  foo(123)
+  bar(321)
diff --git a/tests/macros/texpectIdent2.nim b/tests/macros/texpectIdent2.nim
new file mode 100644
index 000000000..887a6ddc3
--- /dev/null
+++ b/tests/macros/texpectIdent2.nim
@@ -0,0 +1,24 @@
+discard """
+errormsg: "Expected identifier to be `foo` here"
+line: 24
+"""
+
+import macros
+
+macro testTyped(arg: typed): void =
+  arg.expectKind nnkStmtList
+  arg.expectLen 2
+  arg[0].expectKind nnkCall
+  arg[0][0].expectIdent "foo"  # must pass
+  arg[1].expectKind nnkCall
+  arg[1][0].expectIdent "foo"  # must fail
+
+proc foo(arg: int) =
+  discard
+
+proc bar(arg: int) =
+  discard
+
+testTyped:
+  foo(123)
+  bar(321)