path canonicalization for imported modules, relative paths written in rod files
This commit is contained in:
parent
de4b894541
commit
d171a8b36f
10 changed files with 73 additions and 58 deletions
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
|
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
|
||||||
intsets, idgen
|
intsets, idgen, os
|
||||||
|
|
||||||
const
|
const
|
||||||
ImportTablePos* = 0 # imported symbols are at level 0
|
ImportTablePos* = 0 # imported symbols are at level 0
|
||||||
|
|
@ -1030,3 +1030,18 @@ proc getStrOrChar*(a: PNode): string =
|
||||||
internalError(a.info, "getStrOrChar")
|
internalError(a.info, "getStrOrChar")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
|
proc getModuleName*(n: PNode): string =
|
||||||
|
# This returns a short relative module name without the nim extension
|
||||||
|
# e.g. like "system", "importer" or "somepath/module"
|
||||||
|
# The proc won't perform any checks that the path is actually valid
|
||||||
|
case n.kind
|
||||||
|
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||||
|
result = UnixToNativePath(n.strVal)
|
||||||
|
of nkIdent:
|
||||||
|
result = n.ident.s
|
||||||
|
of nkSym:
|
||||||
|
result = n.sym.name.s
|
||||||
|
else:
|
||||||
|
internalError(n.info, "getModuleName")
|
||||||
|
result = ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkImportStmt:
|
of nkImportStmt:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var imported = splitFile(getModuleFile(n.sons[i])).name
|
var imported = getModuleName(n.sons[i])
|
||||||
addDependencyAux(g.module.name.s, imported)
|
addDependencyAux(g.module.name.s, imported)
|
||||||
of nkFromStmt:
|
of nkFromStmt:
|
||||||
var imported = splitFile(getModuleFile(n.sons[0])).name
|
var imported = getModuleName(n.sons[0])
|
||||||
addDependencyAux(g.module.name.s, imported)
|
addDependencyAux(g.module.name.s, imported)
|
||||||
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
|
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
|
||||||
for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])
|
for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])
|
||||||
|
|
|
||||||
|
|
@ -760,21 +760,12 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope =
|
||||||
proc checkForFalse(n: PNode): bool =
|
proc checkForFalse(n: PNode): bool =
|
||||||
result = n.kind == nkIdent and IdentEq(n.ident, "false")
|
result = n.kind == nkIdent and IdentEq(n.ident, "false")
|
||||||
|
|
||||||
proc getModuleFile(n: PNode): string =
|
|
||||||
case n.kind
|
|
||||||
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.strVal
|
|
||||||
of nkIdent: result = n.ident.s
|
|
||||||
of nkSym: result = n.sym.name.s
|
|
||||||
else:
|
|
||||||
internalError(n.info, "getModuleFile()")
|
|
||||||
result = ""
|
|
||||||
|
|
||||||
proc traceDeps(d: PDoc, n: PNode) =
|
proc traceDeps(d: PDoc, n: PNode) =
|
||||||
const k = skModule
|
const k = skModule
|
||||||
if d.section[k] != nil: app(d.section[k], ", ")
|
if d.section[k] != nil: app(d.section[k], ", ")
|
||||||
dispA(d.section[k],
|
dispA(d.section[k],
|
||||||
"<a class=\"reference external\" href=\"$1.html\">$1</a>",
|
"<a class=\"reference external\" href=\"$1.html\">$1</a>",
|
||||||
"$1", [toRope(getModuleFile(n))])
|
"$1", [toRope(getModuleName(n))])
|
||||||
|
|
||||||
proc generateDoc(d: PDoc, n: PNode) =
|
proc generateDoc(d: PDoc, n: PNode) =
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
|
||||||
|
|
@ -16,25 +16,13 @@ import
|
||||||
proc evalImport*(c: PContext, n: PNode): PNode
|
proc evalImport*(c: PContext, n: PNode): PNode
|
||||||
proc evalFrom*(c: PContext, n: PNode): PNode
|
proc evalFrom*(c: PContext, n: PNode): PNode
|
||||||
proc importAllSymbols*(c: PContext, fromMod: PSym)
|
proc importAllSymbols*(c: PContext, fromMod: PSym)
|
||||||
proc getModuleFile*(n: PNode): string
|
|
||||||
# implementation
|
|
||||||
|
|
||||||
proc findModule(info: TLineInfo, modulename: string): string =
|
proc checkModuleName*(n: PNode): string =
|
||||||
# returns path to module
|
# This returns the full canonical path for a given module import
|
||||||
result = options.FindFile(AddFileExt(modulename, nimExt))
|
var modulename = n.getModuleName
|
||||||
if result == "": Fatal(info, errCannotOpenFile, modulename)
|
result = findModule(modulename)
|
||||||
|
if result.len == 0:
|
||||||
proc getModuleFile(n: PNode): string =
|
Fatal(n.info, errCannotOpenFile, modulename)
|
||||||
case n.kind
|
|
||||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
|
||||||
result = findModule(n.info, UnixToNativePath(n.strVal))
|
|
||||||
of nkIdent:
|
|
||||||
result = findModule(n.info, n.ident.s)
|
|
||||||
of nkSym:
|
|
||||||
result = findModule(n.info, n.sym.name.s)
|
|
||||||
else:
|
|
||||||
internalError(n.info, "getModuleFile()")
|
|
||||||
result = ""
|
|
||||||
|
|
||||||
proc rawImportSymbol(c: PContext, s: PSym) =
|
proc rawImportSymbol(c: PContext, s: PSym) =
|
||||||
# This does not handle stubs, because otherwise loading on demand would be
|
# This does not handle stubs, because otherwise loading on demand would be
|
||||||
|
|
@ -103,7 +91,7 @@ proc importAllSymbols(c: PContext, fromMod: PSym) =
|
||||||
proc evalImport(c: PContext, n: PNode): PNode =
|
proc evalImport(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var f = getModuleFile(n.sons[i])
|
var f = checkModuleName(n.sons[i])
|
||||||
var m = gImportModule(f)
|
var m = gImportModule(f)
|
||||||
if sfDeprecated in m.flags:
|
if sfDeprecated in m.flags:
|
||||||
Message(n.sons[i].info, warnDeprecated, m.name.s)
|
Message(n.sons[i].info, warnDeprecated, m.name.s)
|
||||||
|
|
@ -114,7 +102,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
|
||||||
proc evalFrom(c: PContext, n: PNode): PNode =
|
proc evalFrom(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
var f = getModuleFile(n.sons[0])
|
var f = checkModuleName(n.sons[0])
|
||||||
var m = gImportModule(f)
|
var m = gImportModule(f)
|
||||||
n.sons[0] = newSymNode(m)
|
n.sons[0] = newSymNode(m)
|
||||||
addDecl(c, m) # add symbol to symbol table of module
|
addDecl(c, m) # add symbol to symbol table of module
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ proc importModule(filename: string): PSym =
|
||||||
proc CompileModule(filename: string, flags: TSymFlags): PSym =
|
proc CompileModule(filename: string, flags: TSymFlags): PSym =
|
||||||
var rd: PRodReader = nil
|
var rd: PRodReader = nil
|
||||||
var f = addFileExt(filename, nimExt)
|
var f = addFileExt(filename, nimExt)
|
||||||
result = newModule(filename)
|
result = newModule(f)
|
||||||
result.flags = result.flags + flags
|
result.flags = result.flags + flags
|
||||||
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
|
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
|
||||||
rd = handleSymbolFile(result, f)
|
rd = handleSymbolFile(result, f)
|
||||||
|
|
|
||||||
|
|
@ -409,26 +409,34 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo =
|
||||||
result.projPath = projPath
|
result.projPath = projPath
|
||||||
|
|
||||||
proc fileInfoIdx*(filename: string): int32 =
|
proc fileInfoIdx*(filename: string): int32 =
|
||||||
var canonical = canonicalizePath(filename)
|
var
|
||||||
|
canonical: string
|
||||||
|
pseudoPath = false
|
||||||
|
|
||||||
|
try:
|
||||||
|
canonical = canonicalizePath(filename)
|
||||||
|
except:
|
||||||
|
canonical = filename
|
||||||
|
# The compiler uses "filenames" such as `command line` or `stdin`
|
||||||
|
# This flag indicates that we are working with such a path here
|
||||||
|
pseudoPath = true
|
||||||
|
|
||||||
if filenameToIndexTbl.hasKey(canonical):
|
if filenameToIndexTbl.hasKey(canonical):
|
||||||
result = filenameToIndexTbl[canonical]
|
result = filenameToIndexTbl[canonical]
|
||||||
else:
|
else:
|
||||||
result = fileInfos.len.int32
|
result = fileInfos.len.int32
|
||||||
fileInfos.add(newFileInfo(canonical, canonical.shortenDir))
|
fileInfos.add(newFileInfo(canonical, if pseudoPath: "" else: canonical.shortenDir))
|
||||||
filenameToIndexTbl[canonical] = result
|
filenameToIndexTbl[canonical] = result
|
||||||
|
|
||||||
proc newLineInfo*(filename: string, line, col: int): TLineInfo =
|
|
||||||
result.fileIndex = filename.fileInfoIdx
|
|
||||||
result.line = int16(line)
|
|
||||||
result.col = int16(col)
|
|
||||||
|
|
||||||
proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo =
|
proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo =
|
||||||
result.fileIndex = fileInfoIdx
|
result.fileIndex = fileInfoIdx
|
||||||
result.line = int16(line)
|
result.line = int16(line)
|
||||||
result.col = int16(col)
|
result.col = int16(col)
|
||||||
|
|
||||||
fileInfos.add(newFileInfo("command line", ""))
|
proc newLineInfo*(filename: string, line, col: int): TLineInfo {.inline.} =
|
||||||
|
result = newLineInfo(filename.fileInfoIdx, line, col)
|
||||||
|
|
||||||
|
fileInfos.add(newFileInfo("", "command line"))
|
||||||
var gCmdLineInfo* = newLineInfo(int32(0), 1, 1)
|
var gCmdLineInfo* = newLineInfo(int32(0), 1, 1)
|
||||||
|
|
||||||
proc raiseRecoverableError*() {.noinline, noreturn.} =
|
proc raiseRecoverableError*() {.noinline, noreturn.} =
|
||||||
|
|
|
||||||
|
|
@ -188,19 +188,28 @@ iterator iterSearchPath*(): string =
|
||||||
yield it.data
|
yield it.data
|
||||||
it = PStrEntry(it.Next)
|
it = PStrEntry(it.Next)
|
||||||
|
|
||||||
proc rawFindFile(f: string): string =
|
proc rawFindFile(f: string): string =
|
||||||
|
template ret(e: expr) =
|
||||||
|
result = e.canonicalizePath
|
||||||
|
return
|
||||||
|
|
||||||
if ExistsFile(f):
|
if ExistsFile(f):
|
||||||
result = f
|
ret f
|
||||||
else:
|
else:
|
||||||
for it in iterSearchPath():
|
for it in iterSearchPath():
|
||||||
result = JoinPath(it, f)
|
result = JoinPath(it, f)
|
||||||
if ExistsFile(result): return
|
if ExistsFile(result):
|
||||||
|
ret result
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc FindFile*(f: string): string =
|
proc FindFile*(f: string): string =
|
||||||
result = rawFindFile(f)
|
result = rawFindFile(f)
|
||||||
if len(result) == 0: result = rawFindFile(toLower(f))
|
if len(result) == 0: result = rawFindFile(toLower(f))
|
||||||
|
|
||||||
|
proc findModule*(modulename: string): string {.inline.} =
|
||||||
|
# returns path to module
|
||||||
|
result = FindFile(AddFileExt(modulename, nimExt))
|
||||||
|
|
||||||
proc binaryStrSearch*(x: openarray[string], y: string): int =
|
proc binaryStrSearch*(x: openarray[string], y: string): int =
|
||||||
var a = 0
|
var a = 0
|
||||||
var b = len(x) - 1
|
var b = len(x) - 1
|
||||||
|
|
|
||||||
|
|
@ -576,7 +576,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
L = 0
|
L = 0
|
||||||
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
||||||
setlen(r.files, L + 1)
|
setlen(r.files, L + 1)
|
||||||
r.files[L] = decodeStr(r.s, r.pos)
|
var relativePath = decodeStr(r.s, r.pos)
|
||||||
|
var resolvedPath = relativePath.findModule
|
||||||
|
r.files[L] = if resolvedPath.len > 0: resolvedPath else: relativePath
|
||||||
inc(r.pos) # skip #10
|
inc(r.pos) # skip #10
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
inc(L)
|
inc(L)
|
||||||
|
|
@ -628,7 +630,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
r.initIdx = r.pos + 2 # "(\10"
|
r.initIdx = r.pos + 2 # "(\10"
|
||||||
skipSection(r)
|
skipSection(r)
|
||||||
else:
|
else:
|
||||||
MsgWriteln("skipping section: " & $r.pos)
|
MsgWriteln("skipping section: " & section &
|
||||||
|
" at " & $r.pos & " in " & r.filename)
|
||||||
skipSection(r)
|
skipSection(r)
|
||||||
if r.s[r.pos] == '\x0A':
|
if r.s[r.pos] == '\x0A':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
|
|
@ -792,7 +795,7 @@ proc getModuleIdx(filename: string): int =
|
||||||
result = len(gMods)
|
result = len(gMods)
|
||||||
setlen(gMods, result + 1)
|
setlen(gMods, result + 1)
|
||||||
|
|
||||||
proc checkDep(filename: string): TReasonForRecompile =
|
proc checkDep(filename: string): TReasonForRecompile =
|
||||||
assert(not isNil(filename))
|
assert(not isNil(filename))
|
||||||
var idx = getModuleIdx(filename)
|
var idx = getModuleIdx(filename)
|
||||||
if gMods[idx].reason != rrEmpty:
|
if gMods[idx].reason != rrEmpty:
|
||||||
|
|
|
||||||
|
|
@ -87,17 +87,18 @@ proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter =
|
||||||
result.init = ""
|
result.init = ""
|
||||||
result.data = newStringOfCap(12_000)
|
result.data = newStringOfCap(12_000)
|
||||||
|
|
||||||
proc addModDep(w: PRodWriter, dep: string) =
|
proc addModDep(w: PRodWriter, dep: string) =
|
||||||
if w.modDeps.len != 0: add(w.modDeps, ' ')
|
if w.modDeps.len != 0: add(w.modDeps, ' ')
|
||||||
encodeVInt(fileIdx(w, dep), w.modDeps)
|
encodeVInt(fileIdx(w, dep), w.modDeps)
|
||||||
|
|
||||||
const
|
const
|
||||||
rodNL = "\x0A"
|
rodNL = "\x0A"
|
||||||
|
|
||||||
proc addInclDep(w: PRodWriter, dep: string) =
|
proc addInclDep(w: PRodWriter, dep: string) =
|
||||||
|
var resolved = dep.findModule
|
||||||
encodeVInt(fileIdx(w, dep), w.inclDeps)
|
encodeVInt(fileIdx(w, dep), w.inclDeps)
|
||||||
add(w.inclDeps, " ")
|
add(w.inclDeps, " ")
|
||||||
encodeVInt(crcFromFile(dep), w.inclDeps)
|
encodeVInt(crcFromFile(resolved), w.inclDeps)
|
||||||
add(w.inclDeps, rodNL)
|
add(w.inclDeps, rodNL)
|
||||||
|
|
||||||
proc pushType(w: PRodWriter, t: PType) =
|
proc pushType(w: PRodWriter, t: PType) =
|
||||||
|
|
@ -555,21 +556,21 @@ proc process(c: PPassContext, n: PNode): PNode =
|
||||||
# addInterfaceSym(w, a.sons[j].sym);
|
# addInterfaceSym(w, a.sons[j].sym);
|
||||||
# end
|
# end
|
||||||
of nkImportStmt:
|
of nkImportStmt:
|
||||||
for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleFile(n.sons[i]))
|
for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleName(n.sons[i]))
|
||||||
addStmt(w, n)
|
addStmt(w, n)
|
||||||
of nkFromStmt:
|
of nkFromStmt:
|
||||||
addModDep(w, getModuleFile(n.sons[0]))
|
addModDep(w, getModuleName(n.sons[0]))
|
||||||
addStmt(w, n)
|
addStmt(w, n)
|
||||||
of nkIncludeStmt:
|
of nkIncludeStmt:
|
||||||
for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleFile(n.sons[i]))
|
for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleName(n.sons[i]))
|
||||||
of nkPragma:
|
of nkPragma:
|
||||||
addStmt(w, n)
|
addStmt(w, n)
|
||||||
else:
|
else:
|
||||||
nil
|
nil
|
||||||
|
|
||||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||||
if module.id < 0: InternalError("rodwrite: module ID not set")
|
if module.id < 0: InternalError("rodwrite: module ID not set")
|
||||||
var w = newRodWriter(filename, rodread.GetCRC(filename), module)
|
var w = newRodWriter(filename, rodread.GetCRC(module.info.toFullPath), module)
|
||||||
rawAddInterfaceSym(w, module)
|
rawAddInterfaceSym(w, module)
|
||||||
result = w
|
result = w
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -797,7 +797,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
|
||||||
result = newNodeI(nkStmtList, n.info)
|
result = newNodeI(nkStmtList, n.info)
|
||||||
addSon(result, n)
|
addSon(result, n)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var f = getModuleFile(n.sons[i])
|
var f = checkModuleName(n.sons[i])
|
||||||
var fileIndex = f.fileInfoIdx
|
var fileIndex = f.fileInfoIdx
|
||||||
if ContainsOrIncl(c.includedFiles, fileIndex):
|
if ContainsOrIncl(c.includedFiles, fileIndex):
|
||||||
GlobalError(n.info, errRecursiveDependencyX, f)
|
GlobalError(n.info, errRecursiveDependencyX, f)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue