mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
nimsuggest: sane dirty buffer handling
This commit is contained in:
@@ -252,10 +252,11 @@ proc trackDirty(arg: string, info: TLineInfo) =
|
||||
if parseUtils.parseInt(a[3], column) <= 0:
|
||||
localError(info, errInvalidNumber, a[2])
|
||||
|
||||
gDirtyBufferIdx = a[0].fileInfoIdx
|
||||
gDirtyOriginalIdx = a[1].fileInfoIdx
|
||||
|
||||
gTrackPos = newLineInfo(gDirtyBufferIdx, line, column)
|
||||
let dirtyOriginalIdx = a[1].fileInfoIdx
|
||||
if dirtyOriginalIdx >= 0:
|
||||
msgs.setDirtyFile(dirtyOriginalIdx, a[0])
|
||||
|
||||
gTrackPos = newLineInfo(dirtyOriginalIdx, line, column)
|
||||
|
||||
proc track(arg: string, info: TLineInfo) =
|
||||
var a = arg.split(',')
|
||||
|
||||
@@ -169,9 +169,9 @@ proc commandSuggest =
|
||||
# cache in a state where "no recompilation is necessary", but the
|
||||
# cgen pass was never executed at all.
|
||||
commandCompileToC()
|
||||
if gDirtyBufferIdx != 0:
|
||||
discard compileModule(gDirtyBufferIdx, {sfDirty})
|
||||
resetModule(gDirtyBufferIdx)
|
||||
let gDirtyBufferIdx = gTrackPos.fileIndex
|
||||
discard compileModule(gDirtyBufferIdx, {sfDirty})
|
||||
resetModule(gDirtyBufferIdx)
|
||||
else:
|
||||
msgs.gErrorMax = high(int) # do not stop after first error
|
||||
semanticPasses()
|
||||
|
||||
@@ -454,6 +454,9 @@ type
|
||||
# used for better error messages and
|
||||
# embedding the original source in the
|
||||
# generated code
|
||||
dirtyfile: string # the file that is actually read into memory
|
||||
# and parsed; usually 'nil' but is used
|
||||
# for 'nimsuggest'
|
||||
|
||||
TLineInfo*{.final.} = object # This is designed to be as small as possible,
|
||||
# because it is used
|
||||
@@ -597,18 +600,7 @@ proc msgQuit*(x: int8) = quit x
|
||||
proc msgQuit*(x: string) = quit x
|
||||
|
||||
proc suggestQuit*() =
|
||||
when true:
|
||||
raise newException(ESuggestDone, "suggest done")
|
||||
else:
|
||||
if not isServing:
|
||||
assert false
|
||||
quit(0)
|
||||
elif isWorkingWithDirtyBuffer:
|
||||
# No need to compile the rest if we are working with a
|
||||
# throw-away buffer. Incomplete dot expressions frequently
|
||||
# found in dirty buffers will result in errors few steps
|
||||
# from now anyway.
|
||||
raise newException(ESuggestDone, "suggest done")
|
||||
raise newException(ESuggestDone, "suggest done")
|
||||
|
||||
# this format is understood by many text editors: it is the same that
|
||||
# Borland and Freepascal use
|
||||
@@ -644,6 +636,18 @@ proc toFullPath*(fileIdx: int32): string =
|
||||
if fileIdx < 0: result = "???"
|
||||
else: result = fileInfos[fileIdx].fullPath
|
||||
|
||||
proc setDirtyFile*(fileIdx: int32; filename: string) =
|
||||
assert fileIdx >= 0
|
||||
fileInfos[fileIdx].dirtyFile = filename
|
||||
|
||||
proc toFullPathConsiderDirty*(fileIdx: int32): string =
|
||||
if fileIdx < 0:
|
||||
result = "???"
|
||||
elif not fileInfos[fileIdx].dirtyFile.isNil:
|
||||
result = fileInfos[fileIdx].dirtyFile
|
||||
else:
|
||||
result = fileInfos[fileIdx].fullPath
|
||||
|
||||
template toFilename*(info: TLineInfo): string =
|
||||
info.fileIndex.toFilename
|
||||
|
||||
@@ -651,12 +655,12 @@ template toFullPath*(info: TLineInfo): string =
|
||||
info.fileIndex.toFullPath
|
||||
|
||||
proc toMsgFilename*(info: TLineInfo): string =
|
||||
if info.fileIndex < 0: result = "???"
|
||||
if info.fileIndex < 0:
|
||||
result = "???"
|
||||
elif gListFullPaths:
|
||||
result = fileInfos[info.fileIndex].fullPath
|
||||
else:
|
||||
if gListFullPaths:
|
||||
result = fileInfos[info.fileIndex].fullPath
|
||||
else:
|
||||
result = fileInfos[info.fileIndex].projPath
|
||||
result = fileInfos[info.fileIndex].projPath
|
||||
|
||||
proc toLinenumber*(info: TLineInfo): int {.inline.} =
|
||||
result = info.line
|
||||
|
||||
@@ -37,7 +37,7 @@ var
|
||||
|
||||
const
|
||||
seps = {':', ';', ' ', '\t'}
|
||||
Help = "usage: sug|con|def|use dirtybuffer.nim[;originalfile.nim]:line:col\n"&
|
||||
Help = "usage: sug|con|def|use file.nim[;dirtyfile.nim]:line:col\n"&
|
||||
"type 'quit' to quit\n" &
|
||||
"type 'debug' to toggle debug mode on/off\n" &
|
||||
"type 'terse' to toggle terse mode on/off"
|
||||
@@ -59,6 +59,10 @@ proc action(cmd: string) =
|
||||
incl(gGlobalOptions, sw)
|
||||
return
|
||||
|
||||
template err() =
|
||||
echo Help
|
||||
return
|
||||
|
||||
var opc = ""
|
||||
var i = parseIdent(cmd, opc, 0)
|
||||
case opc.normalize
|
||||
@@ -71,35 +75,33 @@ proc action(cmd: string) =
|
||||
of "quit": quit()
|
||||
of "debug": toggle optIdeDebug
|
||||
of "terse": toggle optIdeTerse
|
||||
else:
|
||||
echo Help
|
||||
return
|
||||
else: err()
|
||||
var dirtyfile = ""
|
||||
var orig = ""
|
||||
i = parseQuoted(cmd, dirtyfile, i)
|
||||
i = parseQuoted(cmd, orig, i)
|
||||
if cmd[i] == ';':
|
||||
i = parseQuoted(cmd, orig, i+1)
|
||||
i = parseQuoted(cmd, dirtyfile, i+1)
|
||||
i += skipWhile(cmd, seps, i)
|
||||
var line, col = -1
|
||||
i += parseInt(cmd, line, i)
|
||||
i += skipWhile(cmd, seps, i)
|
||||
i += parseInt(cmd, col, i)
|
||||
if dirtyfile.len != 0:
|
||||
gDirtyBufferIdx = dirtyfile.fileInfoIdx
|
||||
gDirtyOriginalIdx = if orig.len != 0: orig.fileInfoIdx else: gDirtyBufferIdx
|
||||
else:
|
||||
discard "use the same filename as in the last command"
|
||||
resetModule gDirtyBufferIdx
|
||||
if gDirtyBufferIdx != gProjectMainIdx:
|
||||
|
||||
if orig.len == 0: err()
|
||||
let dirtyIdx = orig.fileInfoIdx
|
||||
|
||||
if dirtyfile.len != 0: msgs.setDirtyFile(dirtyIdx, dirtyfile)
|
||||
else: msgs.setDirtyFile(dirtyIdx, nil)
|
||||
|
||||
resetModule dirtyIdx
|
||||
if dirtyIdx != gProjectMainIdx:
|
||||
resetModule gProjectMainIdx
|
||||
gTrackPos = newLineInfo(gDirtyBufferIdx, line, col)
|
||||
gTrackPos = newLineInfo(dirtyIdx, line, col)
|
||||
#echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx
|
||||
gErrorCounter = 0
|
||||
compileProject()
|
||||
|
||||
proc serve() =
|
||||
gDirtyBufferIdx = gProjectMainIdx
|
||||
gDirtyOriginalIdx = gProjectMainIdx
|
||||
# do not stop after the first error:
|
||||
msgs.gErrorMax = high(int)
|
||||
if gUseStdin:
|
||||
|
||||
@@ -114,18 +114,12 @@ var
|
||||
gLastCmdTime*: float # when caas is enabled, we measure each command
|
||||
gListFullPaths*: bool
|
||||
isServing*: bool = false
|
||||
gDirtyBufferIdx* = 0'i32 # indicates the fileIdx of the dirty version of
|
||||
# the tracked source X, saved by the CAAS client.
|
||||
gDirtyOriginalIdx* = 0'i32 # the original source file of the dirtified buffer.
|
||||
gNoNimblePath* = false
|
||||
gExperimentalMode*: bool
|
||||
|
||||
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
||||
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
||||
|
||||
template isWorkingWithDirtyBuffer*: expr =
|
||||
gDirtyBufferIdx != 0
|
||||
|
||||
template compilationCachePresent*: expr =
|
||||
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
|
||||
if rd == nil:
|
||||
openPasses(a, module)
|
||||
if stream == nil:
|
||||
let filename = fileIdx.toFullPath
|
||||
let filename = fileIdx.toFullPathConsiderDirty
|
||||
s = llStreamOpen(filename, fmRead)
|
||||
if s == nil:
|
||||
rawMessage(errCannotOpenFile, filename)
|
||||
|
||||
@@ -45,8 +45,6 @@ proc serve*(action: proc (){.nimcall.}) =
|
||||
curCaasCmd = cmd
|
||||
processCmdLine(passCmd2, cmd)
|
||||
action()
|
||||
gDirtyBufferIdx = 0
|
||||
gDirtyOriginalIdx = 0
|
||||
gErrorCounter = 0
|
||||
|
||||
let typ = getConfigVar("server.type")
|
||||
|
||||
@@ -22,11 +22,7 @@ const
|
||||
|
||||
#template sectionSuggest(): expr = "##begin\n" & getStackTrace() & "##end\n"
|
||||
|
||||
proc origModuleName(m: PSym): string =
|
||||
result = if m.position == gDirtyBufferIdx:
|
||||
fileInfos[gDirtyOriginalIdx].shortName
|
||||
else:
|
||||
m.name.s
|
||||
template origModuleName(m: PSym): string = m.name.s
|
||||
|
||||
proc symToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string =
|
||||
result = section
|
||||
|
||||
@@ -45,7 +45,7 @@ proc parseFile(fileIdx: int32): PNode =
|
||||
var
|
||||
p: TParsers
|
||||
f: File
|
||||
let filename = fileIdx.toFullPath
|
||||
let filename = fileIdx.toFullPathConsiderDirty
|
||||
if not open(f, filename):
|
||||
rawMessage(errCannotOpenFile, filename)
|
||||
return
|
||||
@@ -163,7 +163,7 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
||||
proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
|
||||
var s: PLLStream
|
||||
p.skin = skinStandard
|
||||
let filename = fileIdx.toFullPath
|
||||
let filename = fileIdx.toFullPathConsiderDirty
|
||||
var pipe = parsePipe(filename, inputstream)
|
||||
if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
|
||||
else: s = inputstream
|
||||
|
||||
Reference in New Issue
Block a user