summary refs log tree commit diff stats
diff options
context:
space:
mode:
authoralaviss <alaviss@users.noreply.github.com>2019-10-11 23:04:52 +0700
committerAndreas Rumpf <rumpf_a@web.de>2019-10-11 18:04:52 +0200
commit94c1695be6a81f82de07340fc1c2010281111fad (patch)
treef186c57ba042ff8b9b62c6347e729fbf0fcd56be
parentf957266574652865bc60b289327e6444f9f07f49 (diff)
downloadNim-94c1695be6a81f82de07340fc1c2010281111fad.tar.gz
compiler/options: improve project file detection (#12404)
The compiler can now correctly find the project file of a nimble package.
The algorithm is based on what used by nim.nvim, which has yielded good
results.
-rw-r--r--compiler/options.nim32
1 files changed, 26 insertions, 6 deletions
diff --git a/compiler/options.nim b/compiler/options.nim
index af97ba190..3f7ca4720 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -662,20 +662,40 @@ proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFi
 
 proc findProjectNimFile*(conf: ConfigRef; pkg: string): string =
   const extensions = [".nims", ".cfg", ".nimcfg", ".nimble"]
-  var candidates: seq[string] = @[]
-  var dir = pkg
+  var
+    candidates: seq[string] = @[]
+    dir = pkg
+    nimblepkg = ""
+  let pkgname = pkg.lastPathPart()
   while true:
-    for k, f in os.walkDir(dir, relative=true):
+    for k, f in os.walkDir(dir, relative = true):
       if k == pcFile and f != "config.nims":
         let (_, name, ext) = splitFile(f)
         if ext in extensions:
           let x = changeFileExt(dir / name, ".nim")
           if fileExists(x):
             candidates.add x
+          if ext == ".nimble":
+            if nimblepkg.len == 0:
+              nimblepkg = name
+              # Scan subfolders for package source since nimble supports that.
+              # To save time we only scan with the depth of one as that's the
+              # common scenario.
+              let x = x.extractFilename()
+              for k, d in os.walkDir(dir):
+                if k == pcDir:
+                  for k, f in os.walkDir(d, relative = true):
+                    if k == pcFile and f == x:
+                      candidates.add d / f
+            else:
+              # If we found more than one nimble file, chances are that we
+              # missed the real project file, or this is an invalid nimble
+              # package. Either way, bailing is the better choice.
+              return ""
+    let pkgname = if nimblepkg.len > 0: nimblepkg else: pkgname
     for c in candidates:
-      # nim-foo foo  or  foo  nfoo
-      if (pkg in c) or (c in pkg): return c
-    if candidates.len >= 1:
+      if pkgname in c.extractFilename(): return c
+    if candidates.len > 0:
       return candidates[0]
     dir = parentDir(dir)
     if dir == "": break