nimsuggest: sane dirty buffer handling

This commit is contained in:
Araq
2015-01-29 03:08:41 +01:00
parent ebda8e89e1
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:
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(',')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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