diff options
author | Zahary Karadjov <zahary@gmail.com> | 2013-05-04 23:02:03 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2013-05-04 23:02:03 +0300 |
commit | 519d5b834ad9601c487b4cc183f80b713e2da53f (patch) | |
tree | 3155f9976a7ead7a265d18f1c3b5335921d95dc3 | |
parent | 34cd22ba72e6b93b4f095d6424206627137d0ec6 (diff) | |
download | Nim-519d5b834ad9601c487b4cc183f80b713e2da53f.tar.gz |
experimental support for answering idetools --def requests from
an in-memory index built during compilation in caas mode
-rw-r--r-- | compiler/commands.nim | 3 | ||||
-rw-r--r-- | compiler/main.nim | 20 | ||||
-rw-r--r-- | compiler/msgs.nim | 1 | ||||
-rw-r--r-- | compiler/suggest.nim | 58 |
4 files changed, 72 insertions, 10 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index 27da03bbe..de52a4062 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -215,7 +215,8 @@ proc track(arg: string, info: TLineInfo) = LocalError(info, errInvalidNumber, a[1]) if parseUtils.parseInt(a[2], column) <= 0: 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) = if pass in {passCmd2, passPP}: diff --git a/compiler/main.nim b/compiler/main.nim index 46ef65e81..6e3b1a352 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -16,7 +16,7 @@ import wordrecg, sem, semdata, idents, passes, docgen, extccomp, cgen, jsgen, cgendata, json, nversion, platform, nimconf, importer, passaux, depends, evals, types, idgen, - tables, docgen2, service, magicsys, parser, crc, ccgutils + tables, docgen2, service, magicsys, parser, crc, ccgutils, sigmatch const has_LLVM_Backend = false @@ -64,7 +64,7 @@ proc crcChanged(fileIdx: int32): bool = gMemCacheData[fileIdx].crcStatus = if result: crcHasChanged else: crcNotChanged # echo "TESTING CRC: ", fileIdx.toFilename, " ", result - + case gMemCacheData[fileIdx].crcStatus: of crcHasChanged: result = true @@ -90,18 +90,19 @@ proc addDep(x: Psym, dep: int32) = gMemCacheData[x.position].deps.safeAdd(dep) proc ResetModule(fileIdx: int32) = - echo "HARD RESETTING ", fileIdx.toFilename + writeStackTrace() + # echo "HARD RESETTING ", fileIdx.toFilename gMemCacheData[fileIdx].needsRecompile = Yes gCompiledModules[fileIdx] = nil cgendata.gModules[fileIdx] = nil + resetSourceMap(fileIdx) proc ResetAllModules = for i in 0..gCompiledModules.high: if gCompiledModules[i] != nil: ResetModule(i.int32) - for m in cgenModules(): - echo "CGEN MODULE FOUND" + # for m in cgenModules(): echo "CGEN MODULE FOUND" proc checkDepMem(fileIdx: int32): TNeedRecompile = template markDirty = @@ -112,15 +113,15 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile = return gMemCacheData[fileIdx].needsRecompile if optForceFullMake in gGlobalOptions or - curCaasCmd != lastCaasCmd or - crcChanged(fileIdx): markDirty + crcChanged(fileIdx): + markDirty if gMemCacheData[fileIdx].deps != nil: gMemCacheData[fileIdx].needsRecompile = Probing for dep in gMemCacheData[fileIdx].deps: let d = checkDepMem(dep) if d in { Yes, Recompiled }: - echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d + # echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d markDirty gMemCacheData[fileIdx].needsRecompile = No @@ -381,6 +382,9 @@ proc CommandSuggest = semanticPasses() rodPass() compileProject() + if isServing: + if optDef in gGlobalOptions: + defFromSourceMap(optTrackPos) proc wantMainModule = if gProjectFull.len == 0: diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 6062ebd7f..a1eaf23bb 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -606,6 +606,7 @@ proc `??`* (info: TLineInfo, filename: string): bool = result = filename in info.toFilename var checkPoints*: seq[TLineInfo] = @[] +var optTrackPos*: TLineInfo proc addCheckpoint*(info: TLineInfo) = checkPoints.add(info) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 130666f4d..273347ef3 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -9,7 +9,9 @@ ## This file implements features required for IDE support. -# imported from sigmatch.nim +# included from sigmatch.nim + +import algorithm const sep = '\t' @@ -238,12 +240,66 @@ proc findDefinition(node: PNode, s: PSym) = SuggestWriteln(SymToStr(s, isLocal=false, sectionDef)) 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.} = ## misnamed: should be 'symDeclared' if optUsages in gGlobalOptions: findUsages(n, s) if optDef in gGlobalOptions: findDefinition(n, s) + if isServing: + addToSourceMap(s, n.info) proc markUsed(n: PNode, s: PSym) = incl(s.flags, sfUsed) |