summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-07-19 14:13:16 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-07-19 14:13:23 +0200
commit9eb909baf985b8f6d2b8bc55fee8e67744e9b6fe (patch)
treee799899271ce59556e37856c39ea49a5d80997a8
parentab9e44dc966cba2c57cfff25d42ca927a7942faa (diff)
downloadNim-9eb909baf985b8f6d2b8bc55fee8e67744e9b6fe.tar.gz
fixes #4485; package handling works better; docgen works with --project on Nimble package level
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/docgen.nim20
-rw-r--r--compiler/docgen2.nim20
-rw-r--r--compiler/modules.nim22
-rw-r--r--compiler/options.nim50
-rw-r--r--compiler/packagehandling.nim56
6 files changed, 104 insertions, 66 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 792dd0ea8..9ec88ba8e 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -771,7 +771,7 @@ type
       procInstCache*: seq[PInstantiation]
       gcUnsafetyReason*: PSym  # for better error messages wrt gcsafe
       #scope*: PScope          # the scope where the proc was defined
-    of skModule:
+    of skModule, skPackage:
       # modules keep track of the generic symbols they use from other modules.
       # this is because in incremental compilation, when a module is about to
       # be replaced with a newer version, we must decrement the usage count
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 67092780b..cf03718ca 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -650,22 +650,32 @@ proc generateIndex*(d: PDoc) =
     writeIndexFile(d[], splitFile(options.outFile).dir /
                         splitFile(d.filename).name & IndexExt)
 
+proc getOutFile2(filename, ext, dir: string): string =
+  if gWholeProject:
+    let d = if options.outFile != "": options.outFile else: dir
+    createDir(d)
+    result = d / changeFileExt(filename, ext)
+  else:
+    result = getOutFile(filename, ext)
+
 proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
   var content = genOutFile(d)
   if optStdout in gGlobalOptions:
     writeRope(stdout, content)
   else:
-    writeRope(content, getOutFile(filename, outExt), useWarning)
+    writeRope(content, getOutFile2(filename, outExt, "htmldoc"), useWarning)
 
 proc writeOutputJson*(d: PDoc, filename, outExt: string,
                       useWarning = false) =
-  let content = $d.jArray
+  let content = %*{"orig": d.filename,
+    "nimble": getPackageName(d.filename),
+    "entries": d.jArray}
   if optStdout in gGlobalOptions:
-    write(stdout, content)
+    write(stdout, $content)
   else:
     var f: File
-    if open(f, getOutFile(filename, outExt), fmWrite):
-      write(f, content)
+    if open(f, getOutFile2(filename, outExt, "jsondoc"), fmWrite):
+      write(f, $content)
       close(f)
     else:
       discard "fixme: error report"
diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim
index f83166f2b..03f8ce0cb 100644
--- a/compiler/docgen2.nim
+++ b/compiler/docgen2.nim
@@ -19,25 +19,25 @@ type
     module: PSym
   PGen = ref TGen
 
-proc close(p: PPassContext, n: PNode): PNode =
+template closeImpl(body: untyped) {.dirty.} =
   var g = PGen(p)
   let useWarning = sfMainModule notin g.module.flags
-  if gWholeProject or sfMainModule in g.module.flags:
-    writeOutput(g.doc, g.module.filename, HtmlExt, useWarning)
+  echo g.module.name.s, " ", g.module.owner.id, " ", gMainPackageId
+  if (g.module.owner.id == gMainPackageId and gWholeProject) or
+    sfMainModule in g.module.flags:
+    body
     try:
       generateIndex(g.doc)
     except IOError:
       discard
 
+proc close(p: PPassContext, n: PNode): PNode =
+  closeImpl:
+    writeOutput(g.doc, g.module.filename, HtmlExt, useWarning)
+
 proc closeJson(p: PPassContext, n: PNode): PNode =
-  var g = PGen(p)
-  let useWarning = sfMainModule notin g.module.flags
-  if gWholeProject or sfMainModule in g.module.flags:
+  closeImpl:
     writeOutputJson(g.doc, g.module.filename, ".json", useWarning)
-    try:
-      generateIndex(g.doc)
-    except IOError:
-      discard
 
 proc processNode(c: PPassContext, n: PNode): PNode =
   result = n
diff --git a/compiler/modules.nim b/compiler/modules.nim
index a45de6d72..8df300f5f 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -30,6 +30,9 @@ var
     ## XXX: we should implement recycling of file IDs
     ## if the user keeps renaming modules, the file IDs will keep growing
   gFuzzyGraphChecking*: bool # nimsuggest uses this. XXX figure out why.
+  packageSyms: TStrTable
+
+initStrTable(packageSyms)
 
 proc getModule*(fileIdx: int32): PSym =
   if fileIdx >= 0 and fileIdx < gCompiledModules.len:
@@ -91,6 +94,7 @@ proc resetAllModules* =
     if gCompiledModules[i] != nil:
       resetModule(i.int32)
   resetPackageCache()
+  initStrTable(packageSyms)
   # for m in cgenModules(): echo "CGEN MODULE FOUND"
 
 proc resetAllModulesHard* =
@@ -98,6 +102,7 @@ proc resetAllModulesHard* =
   gCompiledModules.setLen 0
   gMemCacheData.setLen 0
   magicsys.resetSysTypes()
+  initStrTable(packageSyms)
   # XXX
   #gOwners = @[]
 
@@ -140,8 +145,16 @@ proc newModule(fileIdx: int32): PSym =
     rawMessage(errInvalidModuleName, result.name.s)
 
   result.info = newLineInfo(fileIdx, 1, 1)
-  result.owner = newSym(skPackage, getIdent(getPackageName(filename)), nil,
-                        result.info)
+  let pack = getIdent(getPackageName(filename))
+  var packSym = packageSyms.strTableGet(pack)
+  if packSym == nil:
+    let pck = getPackageName(filename)
+    let pck2 = if pck.len > 0: pck else: "unknown"
+    packSym = newSym(skPackage, getIdent(pck2), nil, result.info)
+    initStrTable(packSym.tab)
+    packageSyms.strTableAdd(packSym)
+
+  result.owner = packSym
   result.position = fileIdx
 
   growCache gMemCacheData, fileIdx
@@ -151,6 +164,11 @@ proc newModule(fileIdx: int32): PSym =
   incl(result.flags, sfUsed)
   initStrTable(result.tab)
   strTableAdd(result.tab, result) # a module knows itself
+  let existing = strTableGet(packSym.tab, result.name)
+  if existing != nil and existing.info.fileIndex != result.info.fileIndex:
+    localError(result.info, "module names need to be unique per Nimble package; module clashes with " & existing.info.fileIndex.toFullPath)
+  # strTableIncl() for error corrections:
+  discard strTableIncl(packSym.tab, result)
 
 proc compileModule*(fileIdx: int32, flags: TSymFlags): PSym =
   result = getModule(fileIdx)
diff --git a/compiler/options.nim b/compiler/options.nim
index dcee9eb7d..03ae83587 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -239,6 +239,8 @@ proc removeTrailingDirSep*(path: string): string =
   else:
     result = path
 
+include packagehandling
+
 proc getNimcacheDir*: string =
   result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
                                                          genSubDir
@@ -258,54 +260,6 @@ proc pathSubs*(p, config: string): string =
   if '~' in result:
     result = result.replace("~", home)
 
-template newPackageCache(): expr =
-  newStringTable(when FileSystemCaseSensitive:
-                   modeCaseInsensitive
-                 else:
-                   modeCaseSensitive)
-
-var packageCache = newPackageCache()
-
-proc resetPackageCache*() = packageCache = newPackageCache()
-
-iterator myParentDirs(p: string): string =
-  # XXX os's parentDirs is stupid (multiple yields) and triggers an old bug...
-  var current = p
-  while true:
-    current = current.parentDir
-    if current.len == 0: break
-    yield current
-
-proc getPackageName*(path: string): string =
-  var parents = 0
-  block packageSearch:
-    for d in myParentDirs(path):
-      if packageCache.hasKey(d):
-        #echo "from cache ", d, " |", packageCache[d], "|", path.splitFile.name
-        return packageCache[d]
-      inc parents
-      for file in walkFiles(d / "*.nimble"):
-        result = file.splitFile.name
-        break packageSearch
-      for file in walkFiles(d / "*.babel"):
-        result = file.splitFile.name
-        break packageSearch
-  # we also store if we didn't find anything:
-  if result.isNil: result = ""
-  for d in myParentDirs(path):
-    #echo "set cache ", d, " |", result, "|", parents
-    packageCache[d] = result
-    dec parents
-    if parents <= 0: break
-
-proc withPackageName*(path: string): string =
-  let x = path.getPackageName
-  if x.len == 0:
-    result = path
-  else:
-    let (p, file, ext) = path.splitFile
-    result = (p / (x & '_' & file)) & ext
-
 proc toGeneratedFile*(path, ext: string): string =
   ## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
   var (head, tail) = splitPath(path)
diff --git a/compiler/packagehandling.nim b/compiler/packagehandling.nim
new file mode 100644
index 000000000..c42a4d763
--- /dev/null
+++ b/compiler/packagehandling.nim
@@ -0,0 +1,56 @@
+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2016 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+iterator myParentDirs(p: string): string =
+  # XXX os's parentDirs is stupid (multiple yields) and triggers an old bug...
+  var current = p
+  while true:
+    current = current.parentDir
+    if current.len == 0: break
+    yield current
+
+template newPackageCache(): expr =
+  newStringTable(when FileSystemCaseSensitive:
+                   modeCaseInsensitive
+                 else:
+                   modeCaseSensitive)
+
+var packageCache = newPackageCache()
+
+proc resetPackageCache*() = packageCache = newPackageCache()
+
+proc getPackageName*(path: string): string =
+  var parents = 0
+  block packageSearch:
+    for d in myParentDirs(path):
+      if packageCache.hasKey(d):
+        #echo "from cache ", d, " |", packageCache[d], "|", path.splitFile.name
+        return packageCache[d]
+      inc parents
+      for file in walkFiles(d / "*.nimble"):
+        result = file.splitFile.name
+        break packageSearch
+      for file in walkFiles(d / "*.babel"):
+        result = file.splitFile.name
+        break packageSearch
+  # we also store if we didn't find anything:
+  if result.isNil: result = ""
+  for d in myParentDirs(path):
+    #echo "set cache ", d, " |", result, "|", parents
+    packageCache[d] = result
+    dec parents
+    if parents <= 0: break
+
+proc withPackageName*(path: string): string =
+  let x = path.getPackageName
+  if x.len == 0:
+    result = path
+  else:
+    let (p, file, ext) = path.splitFile
+    result = (p / (x & '_' & file)) & ext