summary refs log tree commit diff stats
path: root/nimpretty
diff options
context:
space:
mode:
Diffstat (limited to 'nimpretty')
-rw-r--r--nimpretty/nimpretty.nim54
-rw-r--r--nimpretty/tester.nim7
-rw-r--r--nimpretty/tests/exhaustive.nim12
-rw-r--r--nimpretty/tests/expected/exhaustive.nim12
-rw-r--r--nimpretty/tests/expected/simple.nim11
-rw-r--r--nimpretty/tests/simple.nim11
6 files changed, 87 insertions, 20 deletions
diff --git a/nimpretty/nimpretty.nim b/nimpretty/nimpretty.nim
index a7940349d..e5abf0d2d 100644
--- a/nimpretty/nimpretty.nim
+++ b/nimpretty/nimpretty.nim
@@ -12,7 +12,7 @@
 when not defined(nimpretty):
   {.error: "This needs to be compiled with --define:nimPretty".}
 
-import ../compiler / [idents, msgs, syntaxes, options, pathutils, layouter]
+import ../compiler / [idents, llstream, ast, msgs, syntaxes, options, pathutils, layouter]
 
 import parseopt, strutils, os, sequtils
 
@@ -48,6 +48,42 @@ type
     indWidth*: Natural
     maxLineLen*: Positive
 
+proc goodEnough(a, b: PNode): bool =
+  if a.kind == b.kind and a.safeLen == b.safeLen:
+    case a.kind
+    of nkNone, nkEmpty, nkNilLit: result = true
+    of nkIdent: result = a.ident.id == b.ident.id
+    of nkSym: result = a.sym == b.sym
+    of nkType: result = true
+    of nkCharLit, nkIntLit..nkInt64Lit, nkUIntLit..nkUInt64Lit:
+      result = a.intVal == b.intVal
+    of nkFloatLit..nkFloat128Lit:
+      result = a.floatVal == b.floatVal
+    of nkStrLit, nkRStrLit, nkTripleStrLit:
+      result = a.strVal == b.strVal
+    else:
+      for i in 0 ..< a.len:
+        if not goodEnough(a[i], b[i]): return false
+      return true
+  elif a.kind == nkStmtList and a.len == 1:
+    result = goodEnough(a[0], b)
+  elif b.kind == nkStmtList and b.len == 1:
+    result = goodEnough(a, b[0])
+  else:
+    result = false
+
+proc finalCheck(content: string; origAst: PNode): bool {.nimcall.} =
+  var conf = newConfigRef()
+  let oldErrors = conf.errorCounter
+  var parser: Parser
+  parser.em.indWidth = 2
+  let fileIdx = fileInfoIdx(conf, AbsoluteFile "nimpretty_bug.nim")
+
+  openParser(parser, fileIdx, llStreamOpen(content), newIdentCache(), conf)
+  let newAst = parseAll(parser)
+  closeParser(parser)
+  result = conf.errorCounter == oldErrors # and goodEnough(newAst, origAst)
+
 proc prettyPrint*(infile, outfile: string, opt: PrettyOptions) =
   var conf = newConfigRef()
   let fileIdx = fileInfoIdx(conf, AbsoluteFile infile)
@@ -58,8 +94,10 @@ proc prettyPrint*(infile, outfile: string, opt: PrettyOptions) =
   parser.em.indWidth = opt.indWidth
   if setupParser(parser, fileIdx, newIdentCache(), conf):
     parser.em.maxLineLen = opt.maxLineLen
-    discard parseAll(parser)
+    let fullAst = parseAll(parser)
     closeParser(parser)
+    when defined(nimpretty):
+      closeEmitter(parser.em, fullAst, finalCheck)
 
 proc main =
   var outfile, outdir: string
@@ -69,8 +107,8 @@ proc main =
 
   var backup = false
     # when `on`, create a backup file of input in case
-    # `prettyPrint` could over-write it (note that the backup may happen even
-    # if input is not actually over-written, when nimpretty is a noop).
+    # `prettyPrint` could overwrite it (note that the backup may happen even
+    # if input is not actually overwritten, when nimpretty is a noop).
     # --backup was un-documented (rely on git instead).
   var opt = PrettyOptions(indWidth: 0, maxLineLen: 80)
 
@@ -78,7 +116,13 @@ proc main =
   for kind, key, val in getopt():
     case kind
     of cmdArgument:
-      infiles.add(key.addFileExt(".nim"))
+      if dirExists(key):
+        for file in walkDirRec(key, skipSpecial = true):
+          if file.endsWith(".nim") or file.endsWith(".nimble"):
+            infiles.add(file)
+      else:
+        infiles.add(key.addFileExt(".nim"))
+
     of cmdLongOption, cmdShortOption:
       case normalize(key)
       of "help", "h": writeHelp()
diff --git a/nimpretty/tester.nim b/nimpretty/tester.nim
index d646b25ce..b1f15aee6 100644
--- a/nimpretty/tester.nim
+++ b/nimpretty/tester.nim
@@ -1,9 +1,10 @@
 # Small program that runs the test cases
 
 import strutils, os, sequtils
+from std/private/gitutils import diffFiles
 
 const
-  dir = "nimpretty/tests/"
+  dir = "nimpretty/tests"
   outputdir = dir / "outputdir"
 
 var
@@ -26,7 +27,7 @@ proc test(infile, ext: string) =
   let produced = dir / nimFile.changeFileExt(ext)
   if readFile(expected) != readFile(produced):
     echo "FAILURE: files differ: ", nimFile
-    discard execShellCmd("diff -uNdr " & expected & " " & produced)
+    echo diffFiles(expected, produced).output
     failures += 1
   else:
     echo "SUCCESS: files identical: ", nimFile
@@ -43,7 +44,7 @@ proc testTogether(infiles: seq[string]) =
     let produced = dir / "outputdir" / infile
     if readFile(expected) != readFile(produced):
       echo "FAILURE: files differ: ", nimFile
-      discard execShellCmd("diff -uNdr " & expected & " " & produced)
+      echo diffFiles(expected, produced).output
       failures += 1
     else:
       echo "SUCCESS: files identical: ", nimFile
diff --git a/nimpretty/tests/exhaustive.nim b/nimpretty/tests/exhaustive.nim
index 30cfc47a9..e5a73305b 100644
--- a/nimpretty/tests/exhaustive.nim
+++ b/nimpretty/tests/exhaustive.nim
@@ -267,7 +267,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
     if not em.endsInWhite: wr(" ")
     wr(tok.ident.s)
     template isUnary(tok): bool =
-      tok.strongSpaceB == 0 and tok.strongSpaceA > 0
+      tok.spacing == {tsLeading}
 
     if not isUnary(tok) or em.lastTok in {tkOpr, tkDotDot}:
       wr(" ")
@@ -693,11 +693,11 @@ proc newRecordGen(ctx: Context; typ: TypRef): PNode =
 String `interpolation`:idx: / `format`:idx: inspired by
 Python's ``f``-strings.
 
-.. code-block:: nim
-
-    import strformat
-    let msg = "hello"
-    doAssert fmt"{msg}\n" == "hello\\n"
+  ```nim
+  import strformat
+  let msg = "hello"
+  doAssert fmt"{msg}\n" == "hello\\n"
+  ```
 
 Because the literal is a raw string literal, the ``\n`` is not interpreted as
 an escape sequence.
diff --git a/nimpretty/tests/expected/exhaustive.nim b/nimpretty/tests/expected/exhaustive.nim
index 82927a11c..7f78b7e56 100644
--- a/nimpretty/tests/expected/exhaustive.nim
+++ b/nimpretty/tests/expected/exhaustive.nim
@@ -272,7 +272,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
     if not em.endsInWhite: wr(" ")
     wr(tok.ident.s)
     template isUnary(tok): bool =
-      tok.strongSpaceB == 0 and tok.strongSpaceA > 0
+      tok.spacing == {tsLeading}
 
     if not isUnary(tok) or em.lastTok in {tkOpr, tkDotDot}:
       wr(" ")
@@ -699,11 +699,11 @@ proc newRecordGen(ctx: Context; typ: TypRef): PNode =
 String `interpolation`:idx: / `format`:idx: inspired by
 Python's ``f``-strings.
 
-.. code-block:: nim
-
-    import strformat
-    let msg = "hello"
-    doAssert fmt"{msg}\n" == "hello\\n"
+  ```nim
+  import strformat
+  let msg = "hello"
+  doAssert fmt"{msg}\n" == "hello\\n"
+  ```
 
 Because the literal is a raw string literal, the ``\n`` is not interpreted as
 an escape sequence.
diff --git a/nimpretty/tests/expected/simple.nim b/nimpretty/tests/expected/simple.nim
index d13558621..e711eb3b6 100644
--- a/nimpretty/tests/expected/simple.nim
+++ b/nimpretty/tests/expected/simple.nim
@@ -16,3 +16,14 @@ proc a() =
 discard ## comment 3
 
 discard # comment 4
+
+
+# bug #20553
+
+let `'hello` = 12
+echo `'hello`
+
+
+proc `'u4`(n: string) =
+  # The leading ' is required.
+  discard
diff --git a/nimpretty/tests/simple.nim b/nimpretty/tests/simple.nim
index 435bd6bd2..2a01a176e 100644
--- a/nimpretty/tests/simple.nim
+++ b/nimpretty/tests/simple.nim
@@ -16,3 +16,14 @@ proc a() =
 discard## comment 3
 
 discard # comment 4
+
+
+# bug #20553
+
+let `'hello` = 12
+echo `'hello`
+
+
+proc `'u4`(n: string) =
+  # The leading ' is required.
+  discard