nimsuggest: sane dirty buffer handling
This commit is contained in:
parent
ebda8e89e1
commit
8710a37384
9 changed files with 51 additions and 56 deletions
|
|
@ -252,10 +252,11 @@ proc trackDirty(arg: string, info: TLineInfo) =
|
||||||
if parseUtils.parseInt(a[3], column) <= 0:
|
if parseUtils.parseInt(a[3], column) <= 0:
|
||||||
localError(info, errInvalidNumber, a[2])
|
localError(info, errInvalidNumber, a[2])
|
||||||
|
|
||||||
gDirtyBufferIdx = a[0].fileInfoIdx
|
let dirtyOriginalIdx = a[1].fileInfoIdx
|
||||||
gDirtyOriginalIdx = a[1].fileInfoIdx
|
if dirtyOriginalIdx >= 0:
|
||||||
|
msgs.setDirtyFile(dirtyOriginalIdx, a[0])
|
||||||
|
|
||||||
gTrackPos = newLineInfo(gDirtyBufferIdx, line, column)
|
gTrackPos = newLineInfo(dirtyOriginalIdx, line, column)
|
||||||
|
|
||||||
proc track(arg: string, info: TLineInfo) =
|
proc track(arg: string, info: TLineInfo) =
|
||||||
var a = arg.split(',')
|
var a = arg.split(',')
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ proc commandSuggest =
|
||||||
# cache in a state where "no recompilation is necessary", but the
|
# cache in a state where "no recompilation is necessary", but the
|
||||||
# cgen pass was never executed at all.
|
# cgen pass was never executed at all.
|
||||||
commandCompileToC()
|
commandCompileToC()
|
||||||
if gDirtyBufferIdx != 0:
|
let gDirtyBufferIdx = gTrackPos.fileIndex
|
||||||
discard compileModule(gDirtyBufferIdx, {sfDirty})
|
discard compileModule(gDirtyBufferIdx, {sfDirty})
|
||||||
resetModule(gDirtyBufferIdx)
|
resetModule(gDirtyBufferIdx)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,9 @@ type
|
||||||
# used for better error messages and
|
# used for better error messages and
|
||||||
# embedding the original source in the
|
# embedding the original source in the
|
||||||
# generated code
|
# 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,
|
TLineInfo*{.final.} = object # This is designed to be as small as possible,
|
||||||
# because it is used
|
# because it is used
|
||||||
|
|
@ -597,17 +600,6 @@ proc msgQuit*(x: int8) = quit x
|
||||||
proc msgQuit*(x: string) = quit x
|
proc msgQuit*(x: string) = quit x
|
||||||
|
|
||||||
proc suggestQuit*() =
|
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
|
# this format is understood by many text editors: it is the same that
|
||||||
|
|
@ -644,6 +636,18 @@ proc toFullPath*(fileIdx: int32): string =
|
||||||
if fileIdx < 0: result = "???"
|
if fileIdx < 0: result = "???"
|
||||||
else: result = fileInfos[fileIdx].fullPath
|
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 =
|
template toFilename*(info: TLineInfo): string =
|
||||||
info.fileIndex.toFilename
|
info.fileIndex.toFilename
|
||||||
|
|
||||||
|
|
@ -651,9 +655,9 @@ template toFullPath*(info: TLineInfo): string =
|
||||||
info.fileIndex.toFullPath
|
info.fileIndex.toFullPath
|
||||||
|
|
||||||
proc toMsgFilename*(info: TLineInfo): string =
|
proc toMsgFilename*(info: TLineInfo): string =
|
||||||
if info.fileIndex < 0: result = "???"
|
if info.fileIndex < 0:
|
||||||
else:
|
result = "???"
|
||||||
if gListFullPaths:
|
elif gListFullPaths:
|
||||||
result = fileInfos[info.fileIndex].fullPath
|
result = fileInfos[info.fileIndex].fullPath
|
||||||
else:
|
else:
|
||||||
result = fileInfos[info.fileIndex].projPath
|
result = fileInfos[info.fileIndex].projPath
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ var
|
||||||
|
|
||||||
const
|
const
|
||||||
seps = {':', ';', ' ', '\t'}
|
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 'quit' to quit\n" &
|
||||||
"type 'debug' to toggle debug mode on/off\n" &
|
"type 'debug' to toggle debug mode on/off\n" &
|
||||||
"type 'terse' to toggle terse mode on/off"
|
"type 'terse' to toggle terse mode on/off"
|
||||||
|
|
@ -59,6 +59,10 @@ proc action(cmd: string) =
|
||||||
incl(gGlobalOptions, sw)
|
incl(gGlobalOptions, sw)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
template err() =
|
||||||
|
echo Help
|
||||||
|
return
|
||||||
|
|
||||||
var opc = ""
|
var opc = ""
|
||||||
var i = parseIdent(cmd, opc, 0)
|
var i = parseIdent(cmd, opc, 0)
|
||||||
case opc.normalize
|
case opc.normalize
|
||||||
|
|
@ -71,35 +75,33 @@ proc action(cmd: string) =
|
||||||
of "quit": quit()
|
of "quit": quit()
|
||||||
of "debug": toggle optIdeDebug
|
of "debug": toggle optIdeDebug
|
||||||
of "terse": toggle optIdeTerse
|
of "terse": toggle optIdeTerse
|
||||||
else:
|
else: err()
|
||||||
echo Help
|
|
||||||
return
|
|
||||||
var dirtyfile = ""
|
var dirtyfile = ""
|
||||||
var orig = ""
|
var orig = ""
|
||||||
i = parseQuoted(cmd, dirtyfile, i)
|
i = parseQuoted(cmd, orig, i)
|
||||||
if cmd[i] == ';':
|
if cmd[i] == ';':
|
||||||
i = parseQuoted(cmd, orig, i+1)
|
i = parseQuoted(cmd, dirtyfile, i+1)
|
||||||
i += skipWhile(cmd, seps, i)
|
i += skipWhile(cmd, seps, i)
|
||||||
var line, col = -1
|
var line, col = -1
|
||||||
i += parseInt(cmd, line, i)
|
i += parseInt(cmd, line, i)
|
||||||
i += skipWhile(cmd, seps, i)
|
i += skipWhile(cmd, seps, i)
|
||||||
i += parseInt(cmd, col, i)
|
i += parseInt(cmd, col, i)
|
||||||
if dirtyfile.len != 0:
|
|
||||||
gDirtyBufferIdx = dirtyfile.fileInfoIdx
|
if orig.len == 0: err()
|
||||||
gDirtyOriginalIdx = if orig.len != 0: orig.fileInfoIdx else: gDirtyBufferIdx
|
let dirtyIdx = orig.fileInfoIdx
|
||||||
else:
|
|
||||||
discard "use the same filename as in the last command"
|
if dirtyfile.len != 0: msgs.setDirtyFile(dirtyIdx, dirtyfile)
|
||||||
resetModule gDirtyBufferIdx
|
else: msgs.setDirtyFile(dirtyIdx, nil)
|
||||||
if gDirtyBufferIdx != gProjectMainIdx:
|
|
||||||
|
resetModule dirtyIdx
|
||||||
|
if dirtyIdx != gProjectMainIdx:
|
||||||
resetModule gProjectMainIdx
|
resetModule gProjectMainIdx
|
||||||
gTrackPos = newLineInfo(gDirtyBufferIdx, line, col)
|
gTrackPos = newLineInfo(dirtyIdx, line, col)
|
||||||
#echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx
|
#echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx
|
||||||
gErrorCounter = 0
|
gErrorCounter = 0
|
||||||
compileProject()
|
compileProject()
|
||||||
|
|
||||||
proc serve() =
|
proc serve() =
|
||||||
gDirtyBufferIdx = gProjectMainIdx
|
|
||||||
gDirtyOriginalIdx = gProjectMainIdx
|
|
||||||
# do not stop after the first error:
|
# do not stop after the first error:
|
||||||
msgs.gErrorMax = high(int)
|
msgs.gErrorMax = high(int)
|
||||||
if gUseStdin:
|
if gUseStdin:
|
||||||
|
|
|
||||||
|
|
@ -114,18 +114,12 @@ var
|
||||||
gLastCmdTime*: float # when caas is enabled, we measure each command
|
gLastCmdTime*: float # when caas is enabled, we measure each command
|
||||||
gListFullPaths*: bool
|
gListFullPaths*: bool
|
||||||
isServing*: bool = false
|
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
|
gNoNimblePath* = false
|
||||||
gExperimentalMode*: bool
|
gExperimentalMode*: bool
|
||||||
|
|
||||||
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
||||||
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
||||||
|
|
||||||
template isWorkingWithDirtyBuffer*: expr =
|
|
||||||
gDirtyBufferIdx != 0
|
|
||||||
|
|
||||||
template compilationCachePresent*: expr =
|
template compilationCachePresent*: expr =
|
||||||
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
|
||||||
if rd == nil:
|
if rd == nil:
|
||||||
openPasses(a, module)
|
openPasses(a, module)
|
||||||
if stream == nil:
|
if stream == nil:
|
||||||
let filename = fileIdx.toFullPath
|
let filename = fileIdx.toFullPathConsiderDirty
|
||||||
s = llStreamOpen(filename, fmRead)
|
s = llStreamOpen(filename, fmRead)
|
||||||
if s == nil:
|
if s == nil:
|
||||||
rawMessage(errCannotOpenFile, filename)
|
rawMessage(errCannotOpenFile, filename)
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,6 @@ proc serve*(action: proc (){.nimcall.}) =
|
||||||
curCaasCmd = cmd
|
curCaasCmd = cmd
|
||||||
processCmdLine(passCmd2, cmd)
|
processCmdLine(passCmd2, cmd)
|
||||||
action()
|
action()
|
||||||
gDirtyBufferIdx = 0
|
|
||||||
gDirtyOriginalIdx = 0
|
|
||||||
gErrorCounter = 0
|
gErrorCounter = 0
|
||||||
|
|
||||||
let typ = getConfigVar("server.type")
|
let typ = getConfigVar("server.type")
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,7 @@ const
|
||||||
|
|
||||||
#template sectionSuggest(): expr = "##begin\n" & getStackTrace() & "##end\n"
|
#template sectionSuggest(): expr = "##begin\n" & getStackTrace() & "##end\n"
|
||||||
|
|
||||||
proc origModuleName(m: PSym): string =
|
template origModuleName(m: PSym): string = m.name.s
|
||||||
result = if m.position == gDirtyBufferIdx:
|
|
||||||
fileInfos[gDirtyOriginalIdx].shortName
|
|
||||||
else:
|
|
||||||
m.name.s
|
|
||||||
|
|
||||||
proc symToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string =
|
proc symToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string =
|
||||||
result = section
|
result = section
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ proc parseFile(fileIdx: int32): PNode =
|
||||||
var
|
var
|
||||||
p: TParsers
|
p: TParsers
|
||||||
f: File
|
f: File
|
||||||
let filename = fileIdx.toFullPath
|
let filename = fileIdx.toFullPathConsiderDirty
|
||||||
if not open(f, filename):
|
if not open(f, filename):
|
||||||
rawMessage(errCannotOpenFile, filename)
|
rawMessage(errCannotOpenFile, filename)
|
||||||
return
|
return
|
||||||
|
|
@ -163,7 +163,7 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
||||||
proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
|
proc openParsers(p: var TParsers, fileIdx: int32, inputstream: PLLStream) =
|
||||||
var s: PLLStream
|
var s: PLLStream
|
||||||
p.skin = skinStandard
|
p.skin = skinStandard
|
||||||
let filename = fileIdx.toFullPath
|
let filename = fileIdx.toFullPathConsiderDirty
|
||||||
var pipe = parsePipe(filename, inputstream)
|
var pipe = parsePipe(filename, inputstream)
|
||||||
if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
|
if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
|
||||||
else: s = inputstream
|
else: s = inputstream
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue