diff options
Diffstat (limited to 'compiler/suggest.nim')
-rw-r--r-- | compiler/suggest.nim | 129 |
1 files changed, 52 insertions, 77 deletions
diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 0700b4140..391906c3f 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -32,7 +32,7 @@ # included from sigmatch.nim -import algorithm, prefixmatches, configuration +import algorithm, prefixmatches, lineinfos from wordrecg import wDeprecated when defined(nimsuggest): @@ -41,31 +41,6 @@ when defined(nimsuggest): const sep = '\t' -type - Suggest* = ref object - section*: IdeCmd - qualifiedPath*: seq[string] - name*: PIdent # not used beyond sorting purposes; name is also - # part of 'qualifiedPath' - filePath*: string - line*: int # Starts at 1 - column*: int # Starts at 0 - doc*: string # Not escaped (yet) - symkind*: TSymKind - forth*: string # type - quality*: range[0..100] # matching quality - isGlobal*: bool # is a global variable - contextFits*: bool # type/non-type context matches - prefix*: PrefixMatch - scope*, localUsages*, globalUsages*: int # more usages is better - tokenLen*: int - Suggestions* = seq[Suggest] - -var - suggestionResultHook*: proc (result: Suggest) {.closure.} - suggestVersion*: int - suggestMaxResults* = 10_000 - #template sectionSuggest(): expr = "##begin\n" & getStackTrace() & "##end\n" template origModuleName(m: PSym): string = m.name.s @@ -104,7 +79,7 @@ proc cmpSuggestions(a, b: Suggest): int = cf globalUsages # if all is equal, sort alphabetically for deterministic output, # independent of hashing order: - result = cmp(a.name.s, b.name.s) + result = cmp(a.name[], b.name[]) proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo; quality: range[0..100]; prefix: PrefixMatch; @@ -117,14 +92,14 @@ proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info result.prefix = prefix result.contextFits = inTypeContext == (s.kind in {skType, skGenericParam}) result.scope = scope - result.name = s.name + result.name = addr s.name.s when defined(nimsuggest): result.globalUsages = s.allUsages.len var c = 0 for u in s.allUsages: if u.fileIndex == info.fileIndex: inc c result.localUsages = c - result.symkind = s.kind + result.symkind = byte s.kind if optIdeTerse notin conf.globalOptions: result.qualifiedPath = @[] if not isLocal and s.kind != skModule: @@ -146,17 +121,18 @@ proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info result.filePath = toFullPath(conf, infox) result.line = toLinenumber(infox) result.column = toColumn(infox) + result.version = conf.suggestVersion proc `$`*(suggest: Suggest): string = result = $suggest.section result.add(sep) if suggest.section == ideHighlight: - if suggest.symkind == skVar and suggest.isGlobal: + if suggest.symkind.TSymKind == skVar and suggest.isGlobal: result.add("skGlobalVar") - elif suggest.symkind == skLet and suggest.isGlobal: + elif suggest.symkind.TSymKind == skLet and suggest.isGlobal: result.add("skGlobalLet") else: - result.add($suggest.symkind) + result.add($suggest.symkind.TSymKind) result.add(sep) result.add($suggest.line) result.add(sep) @@ -164,9 +140,9 @@ proc `$`*(suggest: Suggest): string = result.add(sep) result.add($suggest.tokenLen) else: - result.add($suggest.symkind) + result.add($suggest.symkind.TSymKind) result.add(sep) - if suggest.qualifiedPath != nil: + if suggest.qualifiedPath.len != 0: result.add(suggest.qualifiedPath.join(".")) result.add(sep) result.add(suggest.forth) @@ -179,18 +155,18 @@ proc `$`*(suggest: Suggest): string = result.add(sep) when not defined(noDocgen): result.add(suggest.doc.escape) - if suggestVersion == 0: + if suggest.version == 0: result.add(sep) result.add($suggest.quality) if suggest.section == ideSug: result.add(sep) result.add($suggest.prefix) -proc suggestResult(s: Suggest) = - if not isNil(suggestionResultHook): - suggestionResultHook(s) +proc suggestResult(conf: ConfigRef; s: Suggest) = + if not isNil(conf.suggestionResultHook): + conf.suggestionResultHook(s) else: - suggestWriteln($s) + conf.suggestWriteln($s) proc produceOutput(a: var Suggestions; conf: ConfigRef) = if conf.ideCmd in {ideSug, ideCon}: @@ -198,13 +174,13 @@ proc produceOutput(a: var Suggestions; conf: ConfigRef) = when defined(debug): # debug code writeStackTrace() - if a.len > suggestMaxResults: a.setLen(suggestMaxResults) - if not isNil(suggestionResultHook): + if a.len > conf.suggestMaxResults: a.setLen(conf.suggestMaxResults) + if not isNil(conf.suggestionResultHook): for s in a: - suggestionResultHook(s) + conf.suggestionResultHook(s) else: for s in a: - suggestWriteln($s) + conf.suggestWriteln($s) proc filterSym(s: PSym; prefix: PNode; res: var PrefixMatch): bool {.inline.} = proc prefixMatch(s: PSym; n: PNode): PrefixMatch = @@ -340,7 +316,7 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions) var typ = n.typ var pm: PrefixMatch when defined(nimsuggest): - if n.kind == nkSym and n.sym.kind == skError and suggestVersion == 0: + if n.kind == nkSym and n.sym.kind == skError and c.config.suggestVersion == 0: # consider 'foo.|' where 'foo' is some not imported module. let fullPath = findModule(c.config, n.sym.name.s, toFullPath(c.config, n.info)) if fullPath.len == 0: @@ -397,17 +373,17 @@ type TCheckPointResult* = enum cpNone, cpFuzzy, cpExact -proc inCheckpoint*(current: TLineInfo): TCheckPointResult = - if current.fileIndex == gTrackPos.fileIndex: - if current.line == gTrackPos.line and - abs(current.col-gTrackPos.col) < 4: +proc inCheckpoint*(current, trackPos: TLineInfo): TCheckPointResult = + if current.fileIndex == trackPos.fileIndex: + if current.line == trackPos.line and + abs(current.col-trackPos.col) < 4: return cpExact - if current.line >= gTrackPos.line: + if current.line >= trackPos.line: return cpFuzzy -proc isTracked*(current: TLineInfo, tokenLen: int): bool = - if current.fileIndex==gTrackPos.fileIndex and current.line==gTrackPos.line: - let col = gTrackPos.col +proc isTracked*(current, trackPos: TLineInfo, tokenLen: int): bool = + if current.fileIndex==trackPos.fileIndex and current.line==trackPos.line: + let col = trackPos.col if col >= current.col and col <= current.col+tokenLen-1: return true @@ -425,30 +401,27 @@ when defined(nimsuggest): if infoB.infoToInt == infoAsInt: return s.allUsages.add(info) -var - lastLineInfo*: TLineInfo # XXX global here - proc findUsages(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = - if suggestVersion == 1: - if usageSym == nil and isTracked(info, s.name.s.len): + if conf.suggestVersion == 1: + if usageSym == nil and isTracked(info, conf.m.trackPos, s.name.s.len): usageSym = s - suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) + suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) elif s == usageSym: - if lastLineInfo != info: - suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) - lastLineInfo = info + if conf.lastLineInfo != info: + suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) + conf.lastLineInfo = info when defined(nimsuggest): proc listUsages*(conf: ConfigRef; s: PSym) = #echo "usages ", len(s.allUsages) for info in s.allUsages: let x = if info == s.info and info.col == s.info.col: ideDef else: ideUse - suggestResult(symToSuggest(conf, s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0)) + suggestResult(conf, symToSuggest(conf, s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0)) proc findDefinition(conf: ConfigRef; info: TLineInfo; s: PSym) = if s.isNil: return - if isTracked(info, s.name.s.len): - suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) + if isTracked(info, conf.m.trackPos, s.name.s.len): + suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) suggestQuit() proc ensureIdx[T](x: var T, y: int) = @@ -460,7 +433,7 @@ proc ensureSeq[T](x: var seq[T]) = proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true) {.inline.} = ## misnamed: should be 'symDeclared' when defined(nimsuggest): - if suggestVersion == 0: + if conf.suggestVersion == 0: if s.allUsages.isNil: s.allUsages = @[info] else: @@ -471,14 +444,14 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym; elif conf.ideCmd == ideDef: findDefinition(conf, info, s) elif conf.ideCmd == ideDus and s != nil: - if isTracked(info, s.name.s.len): - suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) + if isTracked(info, conf.m.trackPos, s.name.s.len): + suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) findUsages(conf, info, s, usageSym) - elif conf.ideCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex: - suggestResult(symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0)) - elif conf.ideCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and + elif conf.ideCmd == ideHighlight and info.fileIndex == conf.m.trackPos.fileIndex: + suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0)) + elif conf.ideCmd == ideOutline and info.fileIndex == conf.m.trackPos.fileIndex and isDecl: - suggestResult(symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) + suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) = if s.kind in routineKinds: @@ -519,14 +492,14 @@ proc sugExpr(c: PContext, n: PNode, outputs: var Suggestions) = # of the next line, so we check the 'field' is actually on the same # line as the object to prevent this from happening: let prefix = if n.len == 2 and n[1].info.line == n[0].info.line and - not gTrackPosAttached: n[1] else: nil + not c.config.m.trackPosAttached: n[1] else: nil suggestFieldAccess(c, obj, prefix, outputs) #if optIdeDebug in gGlobalOptions: # echo "expression ", renderTree(obj), " has type ", typeToString(obj.typ) #writeStackTrace() else: - let prefix = if gTrackPosAttached: nil else: n + let prefix = if c.config.m.trackPosAttached: nil else: n suggestEverything(c, n, prefix, outputs) proc suggestExprNoCheck*(c: PContext, n: PNode) = @@ -555,10 +528,10 @@ proc suggestExprNoCheck*(c: PContext, n: PNode) = suggestQuit() proc suggestExpr*(c: PContext, n: PNode) = - if exactEquals(gTrackPos, n.info): suggestExprNoCheck(c, n) + if exactEquals(c.config.m.trackPos, n.info): suggestExprNoCheck(c, n) proc suggestDecl*(c: PContext, n: PNode; s: PSym) = - let attached = gTrackPosAttached + let attached = c.config.m.trackPosAttached if attached: inc(c.inTypeContext) defer: if attached: dec(c.inTypeContext) @@ -574,7 +547,7 @@ proc suggestEnum*(c: PContext; n: PNode; t: PType) = if outputs.len > 0: suggestQuit() proc suggestSentinel*(c: PContext) = - if c.config.ideCmd != ideSug or c.module.position != gTrackPos.fileIndex.int32: return + if c.config.ideCmd != ideSug or c.module.position != c.config.m.trackPos.fileIndex.int32: return if c.compilesContextId > 0: return inc(c.compilesContextId) var outputs: Suggestions = @[] @@ -587,7 +560,9 @@ proc suggestSentinel*(c: PContext) = for it in items(scope.symbols): var pm: PrefixMatch if filterSymNoOpr(it, nil, pm): - outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, newLineInfo(gTrackPos.fileIndex, -1, -1), 0, PrefixMatch.None, false, scopeN)) + outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, + newLineInfo(c.config.m.trackPos.fileIndex, -1, -1), 0, + PrefixMatch.None, false, scopeN)) dec(c.compilesContextId) produceOutput(outputs, c.config) |