# # # The Nim Compiler # (c) Copyright 2017 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## Nimsuggest is a tool that helps to give editors IDE like capabilities. when not defined(nimcore): {.error: "nimcore MUST be defined for Nim's core tooling".} import strutils, os, parseopt, parseutils, sequtils, net, rdstdin, sexp # Do NOT import suggest. It will lead to wierd bugs with # suggestionResultHook, because suggest.nim is included by sigmatch. # So we import that one instead. import compiler / [options, commands, modules, sem, passes, passaux, msgs, nimconf, extccomp, condsyms, sigmatch, ast, scriptconfig, idents, modulegraphs, vm, prefixmatches, lineinfos, cmdlinehelper, pathutils] when defined(windows): import winlean else: import posix const DummyEof = "!EOF!" const Usage = """ Nimsuggest - Tool to give every editor IDE like capabilities for Nim Usage: nimsuggest [options] projectfile.nim Options: --autobind automatically binds into a free port --port:PORT port, by default 6000 --address:HOST binds to that address, by default "" --stdin read commands from stdin and write results to stdout instead of using sockets --epc use emacs epc mode --debug enable debug output --log enable verbose logging to nimsuggest.log file --v1 use version 1 of the protocol; for backwards compatibility --refresh perform automatic refreshes to keep the analysis precise --maxresults:N limit the number of suggestions to N --tester implies --stdin and outputs a line '""" & DummyEof & """' for the tester The server then listens to the connection and takes line-based commands. If --autobind is used, the binded port number will be printed to stdout. In addition, all command line options of Nim that do not affect code generation are supported. """ type Mode = enum mstdin, mtcp, mepc, mcmdsug, mcmdcon CachedMsg = object info: TLineInfo msg: string sev: Severity CachedMsgs = seq[CachedMsg] var gPort = 6000.Port gAddress = "" gMode: Mode gEmitEof: bool # whether we write '!EOF!' dummy lines gLogging = defined(logging) gRefresh: bool gAutoBind = false requests: Channel[string] results: Channel[Suggest] proc writelnToChannel(line: string) = results.send(Suggest(section: ideMsg, doc: line)) proc sugResultHook(s: Suggest) = results.send(s) proc errorHook(conf: ConfigRef; info: TLineInfo; msg: string; sev: Severity) = results.send(Suggest(section: ideChk, filePath: toFullPath(conf, info), line: toLinenumber(info), column: toColumn(info), doc: msg, forth: $sev)) proc myLog(s: string) = if gLogging: log(s) const seps = {':', ';', ' ', '\t'} Help = "usage: sug|con|def|use|dus|chk|mod|highlight|outline|known 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" type EUnexpectedCommand = object of Exception proc parseQuoted(cmd: string; outp: var string; start: int): int = var i = start i += skipWhitespace(cmd, i) if i < cmd.len and cmd[i] == '"': i += parseUntil(cmd, outp, '"', i+1)+2 else: i += parseUntil(cmd, outp, seps, i) result = i proc sexp(s: IdeCmd|TSymKind|PrefixMatch): SexpNode = sexp($s) proc sexp(s: Suggest): SexpNode = # If you change the order here, make sure to change it over in # nim-mode.el too. let qp = if s.qualifiedPath.len == 0: @[] else: s.qualifiedPath result = convertSexp([ s.section, TSymKind s.s
discard """
line: 18
errormsg: "type mismatch"
"""
type
TObj = object {.pure, inheritable.}
TObjB = object of TObj
a, b, c: string
fn: proc (): int {.tags: [].}
EIO2 = ref object of EIO
proc raiser(): int {.tags: [TObj, FWriteIO].} =
writeLine stdout, "arg"
var o: TObjB
o.fn = raiser