nimsuggest: sane dirty buffer handling

This commit is contained in:
Araq 2015-01-29 03:08:41 +01:00
commit 8710a37384
9 changed files with 51 additions and 56 deletions

View file

@ -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(',')

View file

@ -169,9 +169,9 @@ 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:
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
semanticPasses() semanticPasses()

View file

@ -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,18 +600,7 @@ 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")
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")
# 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
# Borland and Freepascal use # Borland and Freepascal use
@ -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,12 +655,12 @@ 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:
result = "???"
elif gListFullPaths:
result = fileInfos[info.fileIndex].fullPath
else: else:
if gListFullPaths: result = fileInfos[info.fileIndex].projPath
result = fileInfos[info.fileIndex].fullPath
else:
result = fileInfos[info.fileIndex].projPath
proc toLinenumber*(info: TLineInfo): int {.inline.} = proc toLinenumber*(info: TLineInfo): int {.inline.} =
result = info.line result = info.line

View file

@ -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:

View file

@ -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 != {}

View file

@ -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)

View file

@ -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")

View file

@ -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

View file

@ -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