fixes #4485; package handling works better; docgen works with --project on Nimble package level
This commit is contained in:
parent
ab9e44dc96
commit
9eb909baf9
6 changed files with 104 additions and 66 deletions
|
|
@ -771,7 +771,7 @@ type
|
||||||
procInstCache*: seq[PInstantiation]
|
procInstCache*: seq[PInstantiation]
|
||||||
gcUnsafetyReason*: PSym # for better error messages wrt gcsafe
|
gcUnsafetyReason*: PSym # for better error messages wrt gcsafe
|
||||||
#scope*: PScope # the scope where the proc was defined
|
#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.
|
# modules keep track of the generic symbols they use from other modules.
|
||||||
# this is because in incremental compilation, when a module is about to
|
# this is because in incremental compilation, when a module is about to
|
||||||
# be replaced with a newer version, we must decrement the usage count
|
# be replaced with a newer version, we must decrement the usage count
|
||||||
|
|
|
||||||
|
|
@ -650,22 +650,32 @@ proc generateIndex*(d: PDoc) =
|
||||||
writeIndexFile(d[], splitFile(options.outFile).dir /
|
writeIndexFile(d[], splitFile(options.outFile).dir /
|
||||||
splitFile(d.filename).name & IndexExt)
|
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) =
|
proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
|
||||||
var content = genOutFile(d)
|
var content = genOutFile(d)
|
||||||
if optStdout in gGlobalOptions:
|
if optStdout in gGlobalOptions:
|
||||||
writeRope(stdout, content)
|
writeRope(stdout, content)
|
||||||
else:
|
else:
|
||||||
writeRope(content, getOutFile(filename, outExt), useWarning)
|
writeRope(content, getOutFile2(filename, outExt, "htmldoc"), useWarning)
|
||||||
|
|
||||||
proc writeOutputJson*(d: PDoc, filename, outExt: string,
|
proc writeOutputJson*(d: PDoc, filename, outExt: string,
|
||||||
useWarning = false) =
|
useWarning = false) =
|
||||||
let content = $d.jArray
|
let content = %*{"orig": d.filename,
|
||||||
|
"nimble": getPackageName(d.filename),
|
||||||
|
"entries": d.jArray}
|
||||||
if optStdout in gGlobalOptions:
|
if optStdout in gGlobalOptions:
|
||||||
write(stdout, content)
|
write(stdout, $content)
|
||||||
else:
|
else:
|
||||||
var f: File
|
var f: File
|
||||||
if open(f, getOutFile(filename, outExt), fmWrite):
|
if open(f, getOutFile2(filename, outExt, "jsondoc"), fmWrite):
|
||||||
write(f, content)
|
write(f, $content)
|
||||||
close(f)
|
close(f)
|
||||||
else:
|
else:
|
||||||
discard "fixme: error report"
|
discard "fixme: error report"
|
||||||
|
|
|
||||||
|
|
@ -19,25 +19,25 @@ type
|
||||||
module: PSym
|
module: PSym
|
||||||
PGen = ref TGen
|
PGen = ref TGen
|
||||||
|
|
||||||
proc close(p: PPassContext, n: PNode): PNode =
|
template closeImpl(body: untyped) {.dirty.} =
|
||||||
var g = PGen(p)
|
var g = PGen(p)
|
||||||
let useWarning = sfMainModule notin g.module.flags
|
let useWarning = sfMainModule notin g.module.flags
|
||||||
if gWholeProject or sfMainModule in g.module.flags:
|
echo g.module.name.s, " ", g.module.owner.id, " ", gMainPackageId
|
||||||
writeOutput(g.doc, g.module.filename, HtmlExt, useWarning)
|
if (g.module.owner.id == gMainPackageId and gWholeProject) or
|
||||||
|
sfMainModule in g.module.flags:
|
||||||
|
body
|
||||||
try:
|
try:
|
||||||
generateIndex(g.doc)
|
generateIndex(g.doc)
|
||||||
except IOError:
|
except IOError:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
proc close(p: PPassContext, n: PNode): PNode =
|
||||||
|
closeImpl:
|
||||||
|
writeOutput(g.doc, g.module.filename, HtmlExt, useWarning)
|
||||||
|
|
||||||
proc closeJson(p: PPassContext, n: PNode): PNode =
|
proc closeJson(p: PPassContext, n: PNode): PNode =
|
||||||
var g = PGen(p)
|
closeImpl:
|
||||||
let useWarning = sfMainModule notin g.module.flags
|
|
||||||
if gWholeProject or sfMainModule in g.module.flags:
|
|
||||||
writeOutputJson(g.doc, g.module.filename, ".json", useWarning)
|
writeOutputJson(g.doc, g.module.filename, ".json", useWarning)
|
||||||
try:
|
|
||||||
generateIndex(g.doc)
|
|
||||||
except IOError:
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc processNode(c: PPassContext, n: PNode): PNode =
|
proc processNode(c: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ var
|
||||||
## XXX: we should implement recycling of file IDs
|
## XXX: we should implement recycling of file IDs
|
||||||
## if the user keeps renaming modules, the file IDs will keep growing
|
## if the user keeps renaming modules, the file IDs will keep growing
|
||||||
gFuzzyGraphChecking*: bool # nimsuggest uses this. XXX figure out why.
|
gFuzzyGraphChecking*: bool # nimsuggest uses this. XXX figure out why.
|
||||||
|
packageSyms: TStrTable
|
||||||
|
|
||||||
|
initStrTable(packageSyms)
|
||||||
|
|
||||||
proc getModule*(fileIdx: int32): PSym =
|
proc getModule*(fileIdx: int32): PSym =
|
||||||
if fileIdx >= 0 and fileIdx < gCompiledModules.len:
|
if fileIdx >= 0 and fileIdx < gCompiledModules.len:
|
||||||
|
|
@ -91,6 +94,7 @@ proc resetAllModules* =
|
||||||
if gCompiledModules[i] != nil:
|
if gCompiledModules[i] != nil:
|
||||||
resetModule(i.int32)
|
resetModule(i.int32)
|
||||||
resetPackageCache()
|
resetPackageCache()
|
||||||
|
initStrTable(packageSyms)
|
||||||
# for m in cgenModules(): echo "CGEN MODULE FOUND"
|
# for m in cgenModules(): echo "CGEN MODULE FOUND"
|
||||||
|
|
||||||
proc resetAllModulesHard* =
|
proc resetAllModulesHard* =
|
||||||
|
|
@ -98,6 +102,7 @@ proc resetAllModulesHard* =
|
||||||
gCompiledModules.setLen 0
|
gCompiledModules.setLen 0
|
||||||
gMemCacheData.setLen 0
|
gMemCacheData.setLen 0
|
||||||
magicsys.resetSysTypes()
|
magicsys.resetSysTypes()
|
||||||
|
initStrTable(packageSyms)
|
||||||
# XXX
|
# XXX
|
||||||
#gOwners = @[]
|
#gOwners = @[]
|
||||||
|
|
||||||
|
|
@ -140,8 +145,16 @@ proc newModule(fileIdx: int32): PSym =
|
||||||
rawMessage(errInvalidModuleName, result.name.s)
|
rawMessage(errInvalidModuleName, result.name.s)
|
||||||
|
|
||||||
result.info = newLineInfo(fileIdx, 1, 1)
|
result.info = newLineInfo(fileIdx, 1, 1)
|
||||||
result.owner = newSym(skPackage, getIdent(getPackageName(filename)), nil,
|
let pack = getIdent(getPackageName(filename))
|
||||||
result.info)
|
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
|
result.position = fileIdx
|
||||||
|
|
||||||
growCache gMemCacheData, fileIdx
|
growCache gMemCacheData, fileIdx
|
||||||
|
|
@ -151,6 +164,11 @@ proc newModule(fileIdx: int32): PSym =
|
||||||
incl(result.flags, sfUsed)
|
incl(result.flags, sfUsed)
|
||||||
initStrTable(result.tab)
|
initStrTable(result.tab)
|
||||||
strTableAdd(result.tab, result) # a module knows itself
|
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 =
|
proc compileModule*(fileIdx: int32, flags: TSymFlags): PSym =
|
||||||
result = getModule(fileIdx)
|
result = getModule(fileIdx)
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,8 @@ proc removeTrailingDirSep*(path: string): string =
|
||||||
else:
|
else:
|
||||||
result = path
|
result = path
|
||||||
|
|
||||||
|
include packagehandling
|
||||||
|
|
||||||
proc getNimcacheDir*: string =
|
proc getNimcacheDir*: string =
|
||||||
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
||||||
genSubDir
|
genSubDir
|
||||||
|
|
@ -258,54 +260,6 @@ proc pathSubs*(p, config: string): string =
|
||||||
if '~' in result:
|
if '~' in result:
|
||||||
result = result.replace("~", home)
|
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 =
|
proc toGeneratedFile*(path, ext: string): string =
|
||||||
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
||||||
var (head, tail) = splitPath(path)
|
var (head, tail) = splitPath(path)
|
||||||
|
|
|
||||||
56
compiler/packagehandling.nim
Normal file
56
compiler/packagehandling.nim
Normal file
|
|
@ -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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue