experimental support for answering idetools --def requests from

an in-memory index built during compilation in caas mode
This commit is contained in:
Zahary Karadjov 2013-05-04 23:02:03 +03:00
commit 519d5b834a
4 changed files with 72 additions and 10 deletions

View file

@ -215,7 +215,8 @@ proc track(arg: string, info: TLineInfo) =
LocalError(info, errInvalidNumber, a[1]) LocalError(info, errInvalidNumber, a[1])
if parseUtils.parseInt(a[2], column) <= 0: if parseUtils.parseInt(a[2], column) <= 0:
LocalError(info, errInvalidNumber, a[2]) LocalError(info, errInvalidNumber, a[2])
msgs.addCheckpoint(newLineInfo(a[0], line, column)) optTrackPos = newLineInfo(a[0], line, column)
msgs.addCheckpoint(optTrackPos)
proc dynlibOverride(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = proc dynlibOverride(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
if pass in {passCmd2, passPP}: if pass in {passCmd2, passPP}:

View file

@ -16,7 +16,7 @@ import
wordrecg, sem, semdata, idents, passes, docgen, extccomp, wordrecg, sem, semdata, idents, passes, docgen, extccomp,
cgen, jsgen, cgendata, json, nversion, cgen, jsgen, cgendata, json, nversion,
platform, nimconf, importer, passaux, depends, evals, types, idgen, platform, nimconf, importer, passaux, depends, evals, types, idgen,
tables, docgen2, service, magicsys, parser, crc, ccgutils tables, docgen2, service, magicsys, parser, crc, ccgutils, sigmatch
const const
has_LLVM_Backend = false has_LLVM_Backend = false
@ -64,7 +64,7 @@ proc crcChanged(fileIdx: int32): bool =
gMemCacheData[fileIdx].crcStatus = if result: crcHasChanged gMemCacheData[fileIdx].crcStatus = if result: crcHasChanged
else: crcNotChanged else: crcNotChanged
# echo "TESTING CRC: ", fileIdx.toFilename, " ", result # echo "TESTING CRC: ", fileIdx.toFilename, " ", result
case gMemCacheData[fileIdx].crcStatus: case gMemCacheData[fileIdx].crcStatus:
of crcHasChanged: of crcHasChanged:
result = true result = true
@ -90,18 +90,19 @@ proc addDep(x: Psym, dep: int32) =
gMemCacheData[x.position].deps.safeAdd(dep) gMemCacheData[x.position].deps.safeAdd(dep)
proc ResetModule(fileIdx: int32) = proc ResetModule(fileIdx: int32) =
echo "HARD RESETTING ", fileIdx.toFilename writeStackTrace()
# echo "HARD RESETTING ", fileIdx.toFilename
gMemCacheData[fileIdx].needsRecompile = Yes gMemCacheData[fileIdx].needsRecompile = Yes
gCompiledModules[fileIdx] = nil gCompiledModules[fileIdx] = nil
cgendata.gModules[fileIdx] = nil cgendata.gModules[fileIdx] = nil
resetSourceMap(fileIdx)
proc ResetAllModules = proc ResetAllModules =
for i in 0..gCompiledModules.high: for i in 0..gCompiledModules.high:
if gCompiledModules[i] != nil: if gCompiledModules[i] != nil:
ResetModule(i.int32) ResetModule(i.int32)
for m in cgenModules(): # for m in cgenModules(): echo "CGEN MODULE FOUND"
echo "CGEN MODULE FOUND"
proc checkDepMem(fileIdx: int32): TNeedRecompile = proc checkDepMem(fileIdx: int32): TNeedRecompile =
template markDirty = template markDirty =
@ -112,15 +113,15 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile =
return gMemCacheData[fileIdx].needsRecompile return gMemCacheData[fileIdx].needsRecompile
if optForceFullMake in gGlobalOptions or if optForceFullMake in gGlobalOptions or
curCaasCmd != lastCaasCmd or crcChanged(fileIdx):
crcChanged(fileIdx): markDirty markDirty
if gMemCacheData[fileIdx].deps != nil: if gMemCacheData[fileIdx].deps != nil:
gMemCacheData[fileIdx].needsRecompile = Probing gMemCacheData[fileIdx].needsRecompile = Probing
for dep in gMemCacheData[fileIdx].deps: for dep in gMemCacheData[fileIdx].deps:
let d = checkDepMem(dep) let d = checkDepMem(dep)
if d in { Yes, Recompiled }: if d in { Yes, Recompiled }:
echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d # echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d
markDirty markDirty
gMemCacheData[fileIdx].needsRecompile = No gMemCacheData[fileIdx].needsRecompile = No
@ -381,6 +382,9 @@ proc CommandSuggest =
semanticPasses() semanticPasses()
rodPass() rodPass()
compileProject() compileProject()
if isServing:
if optDef in gGlobalOptions:
defFromSourceMap(optTrackPos)
proc wantMainModule = proc wantMainModule =
if gProjectFull.len == 0: if gProjectFull.len == 0:

View file

@ -606,6 +606,7 @@ proc `??`* (info: TLineInfo, filename: string): bool =
result = filename in info.toFilename result = filename in info.toFilename
var checkPoints*: seq[TLineInfo] = @[] var checkPoints*: seq[TLineInfo] = @[]
var optTrackPos*: TLineInfo
proc addCheckpoint*(info: TLineInfo) = proc addCheckpoint*(info: TLineInfo) =
checkPoints.add(info) checkPoints.add(info)

View file

@ -9,7 +9,9 @@
## This file implements features required for IDE support. ## This file implements features required for IDE support.
# imported from sigmatch.nim # included from sigmatch.nim
import algorithm
const const
sep = '\t' sep = '\t'
@ -238,12 +240,66 @@ proc findDefinition(node: PNode, s: PSym) =
SuggestWriteln(SymToStr(s, isLocal=false, sectionDef)) SuggestWriteln(SymToStr(s, isLocal=false, sectionDef))
SuggestQuit() SuggestQuit()
type
TSourceMap = object
lines: seq[TLineMap]
TEntry = object
pos: int
sym: PSym
TLineMap = object
entries: seq[TEntry]
var
gSourceMaps: seq[TSourceMap] = @[]
proc ensureIdx[T](x: var T, y: int) =
if x.len <= y: x.setLen(y+1)
proc ensureSeq[T](x: var seq[T]) =
if x == nil: newSeq(x, 0)
proc resetSourceMap*(fileIdx: int32) =
ensureIdx(gSourceMaps, fileIdx)
gSourceMaps[fileIdx].lines = @[]
proc addToSourceMap(sym: Psym, info: TLineInfo) =
ensureIdx(gSourceMaps, info.fileIndex)
ensureSeq(gSourceMaps[info.fileIndex].lines)
ensureIdx(gSourceMaps[info.fileIndex].lines, info.line)
ensureSeq(gSourceMaps[info.fileIndex].lines[info.line].entries)
gSourceMaps[info.fileIndex].lines[info.line].entries.add(TEntry(pos: info.col, sym: sym))
proc defFromLine(entries: var seq[TEntry], col: int32) =
# The sorting is done lazily here on purpose.
# No need to pay the price for it unless the user requests
# "goto definition" on a particular line
sort(entries) do (a,b: TEntry) -> int:
return cmp(a.pos, b.pos)
for e in entries:
# currently, the line-infos for most expressions point to
# one position past the end of the expression. This means
# that the first expr that ends after the cursor column is
# the one we are looking for.
if e.pos >= col:
SuggestWriteln(SymToStr(e.sym, isLocal=false, sectionDef))
return
proc defFromSourceMap*(i: TLineInfo) =
InternalAssert i.fileIndex < gSourceMaps.len and
i.line < gSourceMaps[i.fileIndex].lines.len
defFromLine(gSourceMaps[i.fileIndex].lines[i.line].entries, i.col)
proc suggestSym*(n: PNode, s: PSym) {.inline.} = proc suggestSym*(n: PNode, s: PSym) {.inline.} =
## misnamed: should be 'symDeclared' ## misnamed: should be 'symDeclared'
if optUsages in gGlobalOptions: if optUsages in gGlobalOptions:
findUsages(n, s) findUsages(n, s)
if optDef in gGlobalOptions: if optDef in gGlobalOptions:
findDefinition(n, s) findDefinition(n, s)
if isServing:
addToSourceMap(s, n.info)
proc markUsed(n: PNode, s: PSym) = proc markUsed(n: PNode, s: PSym) =
incl(s.flags, sfUsed) incl(s.flags, sfUsed)