Luacheck FAR scripts — статический анализатор для Lua/MoonScript

Здесь обсуждается всё, что касается макросов.
User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

Luacheck FAR scripts — статический анализатор для Lua/MoonScript

Post by John Doe » Tue 16 Jun, 2015 12:36

Luacheck это статический анализатор для Lua.
Luacheck может обнаруживать разнообразные проблемы, такие как использование неопределённых глобальных переменных, неиспользованные переменные и значения, доступ к неинициализированным переменным, недостижимый код и многое другое.

А для удобной работы с luacheck в фаре предлагаю данный пакет скриптов, обеспечивающий работу Luacheck в редакторе и в командной строке.
Кроме того, в редакторе для Luacheck обеспечивается прозрачная "трансляция" MoonScript, что позволяет анализировать и *.moon-файлы.

Инструкции по установке, настройке, и работе — во встроенной справке.

Требования:
  • FAR 3 не старше b4831
  • luacheck не ниже v0.19
Attachments
luaсheck_far_v1.4.7z
(21.55 KiB) Downloaded 15 times
Last edited by John Doe on Sun 08 Oct, 2017 14:21, edited 1 time in total.

User avatar
HaRT
Moderator
Posts: 8118
Joined: Tue 30 Aug, 2005 17:21
Location: Санкт-Петербург
Has thanked: 68 times
Been thanked: 106 times

luacheck — статический анализатор для Lua

Post by HaRT » Tue 21 Jun, 2016 13:45

Latest post of the previous page:

John Doe wrote: CODE: [ВЫДЕЛИТЬ ВСЁ] [EXPAND/COLLAPSE] [DOWNLOAD] (LUACHECK_EDITOR.LUA)
Спасибо, вижу, что по нажатию на [b]CtrlH[/b] список фильтруется в соответствии с [b]options_alt.only[/b]. Несколько соображений:
1. Слово alt у меня не вызывает никаких ассоциаций с происходящим, я бы предпочёл раздедение major/minor, primary/secondary, …. Ну или объясните, пожалуйста, как бы это лучше осознать и запомнить.
2. Обнаружился неприятный эффект: если после фильтрации список оказался пуст, то кратковременно показывается сообщение “No warnings” и список уже не открывается (если вдуматься, это и не удивительно), но вот фильтр после этого снимается только перезагрузкой макросов — неудобно. Предлагаю, чтобы при включенной фильтрации список показывался, даже если он пустой.
3. Чтобы короткий/пустой список не создавал иллюзию чистого кода, предлагаю в качестве признака отфильтрованности добавить, например, звёздочку в название меню. (Например, AltHistory так индицирует тип фильтра: от начала или в любом месте строки.)
4. Хорошо бы добавить [b]CtrlH[/b] в подсказку на нижней рамке и в Справку.
Фар есть инструмент, а не нянька. © 2009 DrKnS

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Tue 21 Jun, 2016 14:22

HaRT wrote: Слово alt у меня не вызывает никаких ассоциаций с происходящим,
Альтернативный набор опций. Настраивается в начале файла, таблицей options_alt. Если хотите, то можно переименовать (параметр и/или шорткат)
HaRT wrote: после этого снимается только перезагрузкой макросов
Это ошибка, исправил
HaRT wrote: Предлагаю, чтобы при включенной фильтрации список показывался, даже если он пустой.
По сути это не фильтрация, а только лишь использование другого набора опций.

И я тут глянул, чтобы "нормально" показать пустой список потребуется добавить слишком много костылей.

P.S.
Возможно вот этого вам хватит, здесь просто скрывается всё что не начинается на "1", но зато список не закрывается.
  1. local _NAME,_VER = "luacheck","1.2H"
  2. local _forumtopic = "http://forum.farmanager.com/viewtopic.php?f=15&t=9650"
  3. local luacheck_min_version,lmv_err_msg = "0.11.0","luacheck version %s or newer expected"
  4. -- list options
  5. local O = {
  6.   MaxHeight = 10,
  7.   InitPos   = "Bottom", --Top,Bottom,Center
  8.   AutoPos   = true,
  9.   --CycleMode = "ping-pong",
  10.   --ConvertToAnsi = true,
  11. }
  12.  
  13. -- luacheck options
  14. local options = { --http://luacheck.readthedocs.org/en/0.11.0/config.html
  15.   new_read_globals={
  16.     "Macro","NoMacro","Event","NoEvent","MenuItem","NoMenuItem","CommandLine","NoCommandLine",
  17.   };
  18.   new_globals={
  19.     "_filename",                    --scripts executed in luamacro via cmdline prefix
  20.     "export","IsLuaStateRecreated", --lua plugins
  21.   }
  22.  
  23.   --global=false;
  24.   --allow_defined=true;
  25.   --allow_defined_top=true;
  26.   --unused=false;
  27.   --unused_args=false;
  28.   --unused_secondaries=false;
  29.   --redefined=false;
  30.   --http://luacheck.readthedocs.org/en/0.11.0/cli.html#patterns
  31.   --ignore={"4../.*"};
  32.   --enable={};
  33.   --only={};
  34. }
  35. local only_globals
  36.  
  37. local function showHelp()
  38.   if far.Message([[
  39. Основные действия:
  40. • Enter           - перейти к позиции предупреждения
  41. • Esc             - закрыть список и восстановить исходную позицию
  42.  
  43. Дополнительные действия (не закрывают список):
  44. • Ctrl-PgUp       - перейти к позиции, на которую ссылается предупреждение
  45. • Ctrl-Up/Down    - скроллировать текст редактора
  46.  
  47. Управление расположением списка:
  48. • Ctrl-Home, Num7 - вверху
  49. • Ctrl-End,  Num1 - внизу
  50. • Num4            - по центру
  51. • F6, Divide      - перебор режимов
  52. • F5, Num5        - максимизация
  53.  
  54. Действия с закладками
  55. • Ctrl-0..9       - перейти к позиции закладки 0..9
  56. • Ctrl-Shift-0..9 - установить закладку 0..9 в текущей позиции
  57. • Add             - добавить сессионную закладку с текущей позицией]],
  58. ("%s v%s"):format(_NAME,_VER),"OK;Go to forum;","l")==2 then win.ShellExecute(nil,"open",_forumtopic) end
  59. end
  60. --todo
  61. --• Ctrl-Shift-Enter,
  62. --  Ctrl-Enter      - перейти к позиции предупреждения
  63. --• Shift-Up,  Num2 - перейти к предыдущему предупреждению
  64. --• Shift-Down,Num8 - перейти к следующему предупреждению
  65.  
  66. local luacheck = require "luacheck"
  67. if luacheck._VERSION<luacheck_min_version then error(lmv_err_msg:format(luacheck_min_version)) end
  68.  
  69. local function MessagePopup(msg,title,flags,delay)
  70.   local s = far.SaveScreen()
  71.   far.Message(msg,title or "","",flags)
  72.   win.Sleep(delay or 500); far.RestoreScreen(s)
  73. end
  74.  
  75. local Id = "CFD31C22-0D17-4D87-829A-14561B529D34"
  76. local function expandBreakKeys(BreakKeysArr)
  77.   local newBreakKeysArr = {}
  78.   for _,item in ipairs(BreakKeysArr) do
  79.     if item then
  80.       for key in item.BreakKey:gmatch("%S+") do
  81.         local newitem = {}
  82.         for k,v in pairs(item) do newitem[k]=v end
  83.         newitem.BreakKey = key
  84.         table.insert(newBreakKeysArr,newitem)
  85.       end
  86.     end
  87.   end
  88.   return newBreakKeysArr
  89. end
  90.  
  91. local function setEditorPos(info) editor.SetPosition(nil,info); editor.Redraw() end
  92.  
  93. local bak_pos
  94. local function restorePos()
  95.   if bak_pos then
  96.     editor.Select(nil,bak_pos)
  97.     setEditorPos(bak_pos)
  98.   end
  99. end
  100.  
  101. local function scrollEditor(dir)
  102.   local ei = editor.GetInfo()
  103.   ei.TopScreenLine = ei.TopScreenLine+dir
  104.   if ei.TopScreenLine<1 or ei.TopScreenLine>ei.TotalLines-ei.WindowSizeY+1 then mf.beep(); return end
  105.   if ei.CurLine-ei.TopScreenLine-(dir==1 and -1 or ei.WindowSizeY)==0 then
  106.     ei.CurLine = ei.CurLine+dir
  107.   end
  108.   setEditorPos(ei)
  109. end
  110.  
  111. local F = far.Flags
  112.  
  113. local list = {}
  114. function list:calcProps(Items,Props)
  115.   self.Pos = self.Pos or O.InitPos
  116.   Items = assert(Items or self.Items,"Items not set")
  117.   local nItems = #Items
  118.   Props = assert(Props or self.Props,"Props not set")
  119.   -- calculate required list's dimensions and position
  120.   local r = far.AdvControl(F.ACTL_GETFARRECT)
  121.   local xSize,ySize = r.Right-r.Left,r.Bottom-r.Top --Far size
  122.   local MaxItems = ySize-3 --max items n to fit
  123.   local X,Y
  124.   X = Items.maxlen<xSize-4 and (xSize-Items.maxlen)/2-2 or -1
  125.   local nLines = math.min(nItems,O.MaxHeight,MaxItems) --actual list lines n
  126.   local Pos = self.Pos or O.InitPos
  127.   local isMaximizable = nItems>nLines and nLines<MaxItems
  128.   local isMaximized = self.isMaximized and isMaximizable
  129.   if Pos=="Center" or isMaximized then
  130.     X,Y = -1,-1
  131.   elseif Pos=="Top" then
  132.     Y = 0
  133.   elseif Pos=="Bottom" then
  134.     Y = MaxItems-nLines>0 and MaxItems-nLines+1+1 or -1
  135.   end
  136.   -- set properties
  137.   Props.X,Props.Y,Props.MaxHeight = X,Y,isMaximized and 0 or O.MaxHeight
  138.   self.Props,self.Items,self.nItems = Props,Items,nItems
  139.   self.nLines,self.isMaximized = nLines,isMaximized
  140.   self.EditorShiftTop = Far.GetConfig"Editor.ShowTitleBar" and 0 or 1
  141.   self.EditorShiftBottom = Far.KeyBar_Show()-1
  142. end
  143. function list:maximize(state)
  144.   self.isMaximized = state==nil and not self.isMaximized or state
  145.   self:calcProps()
  146. end
  147. function list:setPos(Pos)
  148.   if Pos==self.Pos then
  149.     return list:maximize()
  150.   elseif Pos=="ping-pong" then
  151.     if self.Pos=="Center" then
  152.       Pos = self.prevPos=="Top" and "Bottom" or "Top"
  153.     else
  154.       Pos = "Center"
  155.     end
  156.   elseif not Pos then
  157.     local next = {["Top"]="Bottom",["Bottom"]="Center",["Center"]="Top"}
  158.     Pos = next[self.Pos]
  159.   end
  160.   self.prevPos = Pos~="Center" and Pos or self.prevPos
  161.   self.Pos = Pos
  162.   self.isMaximized = false
  163.   self:calcProps()
  164. end
  165. function list:gotoWarning(pos,to_prev,force_top)
  166.   local w = self.Items[pos]
  167.   local line = to_prev and w.prev_line or w.line
  168.   if not line then return end
  169.   local column = to_prev and w.prev_column or w.column
  170.   local end_column = not to_prev and w.end_column
  171.   --select
  172.   local width
  173.   if end_column then
  174.     width = end_column-column+1
  175.   elseif w.name then
  176.     width = w.name:len()
  177.   else
  178.     local str = editor.GetString(nil,line)
  179.     if not str then return end
  180.     local a,b = str.StringText:find("^%S+",column)
  181.     width = a and b-a+1 or str.StringLength-column+1
  182.   end
  183.   editor.Select(nil,F.BTYPE_STREAM,line,column,width,1)
  184.   --goto
  185.   local nLines,TopScreenLine = self.nLines
  186.   if nLines then --trying to correct TopScreenLine in order not to let cursor be hidden behind list
  187.     local ei = editor.GetInfo()
  188.     local y = line-ei.TopScreenLine --calculated screen line of warning
  189.     local a,b = 0,ei.WindowSizeY    --valid screen lines (a..b)
  190.     if self.Pos=="Top" then
  191.       a = a+nLines+3+self.EditorShiftTop
  192.     elseif self.Pos=="Bottom" then
  193.       b = b-nLines-4+1+self.EditorShiftBottom
  194.     end
  195.     TopScreenLine = (y<a or force_top) and math.max(line-a,1)
  196.                  or (y>b)              and line-b
  197.     --win.OutputDebugString(("%s…%s = %s = %s"):format(a,b,y,TopScreenLine or '-'))
  198.   end
  199.   setEditorPos{CurLine=line,CurPos=column,TopScreenLine=TopScreenLine}
  200. end
  201. function list:Up(pos)   return pos-1>=1 and pos-1 or self.nItems end
  202. function list:Down(pos) return pos+1<=self.nItems and pos+1 or 1 end
  203. local function go(dir,pos,autopos)
  204.   local nextpos = list[dir](list,pos)
  205.   if autopos then list:gotoWarning(nextpos) end
  206.   return nextpos
  207. end
  208.  
  209. local Check --fw decl
  210. local bKeys = expandBreakKeys {
  211.   {BreakKey="C+UP   C+NUMPAD8 C+8",action=function() scrollEditor(-1) end},
  212.   {BreakKey="C+DOWN C+NUMPAD2 C+2",action=function() scrollEditor(1) end},
  213.   {BreakKey="C+RETURN C+NEXT C+NUMPAD3 C+3",action=function(pos) list:gotoWarning(pos) end},
  214.   {BreakKey="CS+RETURN",        action=function(pos) list:gotoWarning(pos,nil,true) end},
  215.   {BreakKey="RETURN",           action=function(pos)
  216.      if list.Props.SelectIndex~=pos then list:gotoWarning(pos) end
  217.      return "break"
  218.    end},
  219.   {BreakKey="ESCAPE",           action=function() restorePos(); return "break" end},
  220.   {BreakKey="C+PRIOR C+NUMPAD9 C+9",action=function(pos) list:gotoWarning(pos,true) end},
  221.   {BreakKey="C+HOME NUMPAD7 7", action=function() list:setPos("Top") end},
  222.   {BreakKey="C+END  NUMPAD1 1", action=function() list:setPos("Bottom") end},
  223.   {BreakKey="NUMPAD4 4",        action=function() list:setPos("Center") end},
  224.   {BreakKey="F6 DIVIDE",        action=function() list:setPos(O.CycleMode) end},
  225.   {BreakKey="F5 CLEAR 5",       action=function() list:maximize() end},
  226.   {BreakKey="ADD",              action=function() editor.AddSessionBookmark() end},
  227.   {BreakKey="CS+1 CS+2 CS+3 CS+4 CS+5 CS+6 CS+7 CS+8 CS+9 CS+0 C+1 C+2 C+3 C+4 C+5 C+6 C+7 C+8 C+9 C+0",keys=true},
  228.   {BreakKey="F1",               action=showHelp},
  229.   --http://bugs.farmanager.com/view.php?id=1301#c12736
  230.   {BreakKey="UP",               action=function(pos) return go("Up",pos,O.AutoPos) end},
  231.   {BreakKey="S+UP NUMPAD8 8",   action=function(pos) return go("Up",pos,not O.AutoPos) end},
  232.   {BreakKey="DOWN",             action=function(pos) return go("Down",pos,O.AutoPos) end},
  233.   {BreakKey="S+DOWN NUMPAD2 2", action=function(pos) return go("Down",pos,not O.AutoPos) end},
  234.   --{BreakKey="F3",               action=function(pos) require"le"(list.Items[pos],"Event") end},
  235.   --{BreakKey="F9",               action=function() require"le"(O,"Options");list:calcProps() end},
  236.   {BreakKey="C+H",              action=function(_,Items)
  237.      only_globals = not only_globals
  238.      for i=1,#Items do
  239.        local item = Items[i]
  240.        item.hidden = only_globals and item.code and item.code:sub(1,1)~="1"
  241.      end
  242.    end},
  243. }
  244.  
  245. local Props = {
  246.   Title=_NAME;
  247.   Bottom="Ctrl-Enter, Ctrl-Up/Down, F5, F6, F1";
  248.   Id=win.Uuid(Id);
  249. }
  250.  
  251. function Check()
  252.   local ei = editor.GetInfo()
  253.   local sel = editor.GetSelection()
  254.   if sel then --save for further restoring
  255.     ei.BlockStartPos = sel.StartPos
  256.     ei.BlockWidth = sel.EndPos-sel.StartPos+1
  257.     ei.BlockHeight = sel.EndLine-sel.StartLine+1
  258.   end
  259.   bak_pos = ei
  260.   local source = {}
  261.   for i=1,ei.TotalLines do source[i] = editor.GetString(nil,i).StringText end
  262.   local text = table.concat(source,"\n")
  263.   if O.ConvertToAnsi then
  264.     text = win.WideCharToMultiByte(win.Utf8ToUtf16(text),win.GetACP())
  265.   end
  266.   local report = luacheck.check_strings({text}, options)[1]
  267.   if not report then
  268.     far.Message("Internal error: unable to get report",_NAME,nil,"w")
  269.     return
  270.   end
  271.   if #report==0 then
  272.     MessagePopup("No warnings",_NAME)
  273.   else -- proceed with warnings list
  274.     local Items,pos,maxlen,err = {},nil,0
  275.     for i,w in ipairs(report) do
  276.       err = w.code:sub(1,1)=="0"
  277.       w.text =  ("%4u:%-3u "):format(w.line,w.column)..
  278.                 ("│ %s%s │ "):format(err and "E" or "W",w.code)..
  279.                 luacheck.get_message(w)
  280.       local len = w.text:len()
  281.       maxlen = len>maxlen and len or maxlen
  282.       w.checked = err and "‼" or w.code:sub(1,1)=="1" and "!" --[[??]] or w.secondary and "²"
  283.       if not pos and w.line==ei.CurLine and w.column==ei.CurPos then pos = i end
  284.       Items[i] = w
  285.       if not w.end_column then mf.beep() end--??
  286.     end
  287.     Items.maxlen = maxlen
  288.     if err then mf.beep(); mf.postmacro(MessagePopup,"Errors found!",_NAME,"w",300) end
  289.     list:calcProps(Items,Props)
  290.     if O.AutoPos then list:gotoWarning(pos or 1) end
  291.     repeat --todo use dialog instead of menu
  292.       -- show list
  293.       Props.SelectIndex = pos
  294.       local item
  295.       item,pos = far.Menu(Props,Items,bKeys)
  296.       -- process breakkeys
  297.       if not item then
  298.         break
  299.       elseif item.keys then
  300.         Keys(item.BreakKey:gsub("^CS%+","CtrlShift"):gsub("^C%+","Ctrl"))
  301.       elseif not item.action then
  302.         list:gotoWarning(pos)
  303.       else
  304.         pos = item.action(pos,Items) or pos
  305.         if pos=="break" then break end
  306.       end
  307.     until false
  308.     only_globals = false
  309.   end
  310. end
  311.  
  312. Event { description="luacheck menu handler";
  313.   group="DialogEvent";
  314.   action=function(Event,param)
  315.     local hDlg,Msg = param.hDlg,param.Msg
  316.     if Msg==F.DN_RESIZECONSOLE then
  317.       if Event==F.DE_DLGPROCINIT and Menu.Id==Id then
  318.         hDlg:send(F.DM_CLOSE,-1,0)
  319.         list:calcProps()
  320.       end
  321.     elseif Msg==F.DN_INITDIALOG and Event==F.DE_DLGPROCINIT then
  322.       local info = hDlg:send(F.DM_GETDIALOGINFO)
  323.       if info and info.Id==win.Uuid(Id) then
  324.         local r = hDlg:send(F.DM_GETITEMPOSITION,1)
  325.         hDlg:send(F.DM_SETITEMPOSITION,1,{Left=r.Left-2,Top=r.Top-1,Right=r.Right-2,Bottom=r.Bottom-1})
  326.         r = hDlg:send(F.DM_GETDLGRECT)
  327.         hDlg:send(F.DM_RESIZEDIALOG,0,{Y=r.Bottom-r.Top-1,X=r.Right-r.Left-3})
  328.         hDlg:send(F.DM_MOVEDIALOG,0,{X=2,Y=list.Pos=="Bottom" and 1 or 0})
  329.       end
  330.     end
  331.   end
  332. }
  333.  
  334. Macro { description="luacheck menu helper";
  335.   area="Menu";  key="ShiftUp ShiftDown";    flags="NoSendKeysToPlugins";
  336.   uid="60596FEB-E7C5-47A5-A3C9-B782C8F8EF93";
  337.   condition=function()return O.AutoPos and Menu.Id==Id end;
  338.   action=function()
  339.     Keys(mf.akey(1,1):match"Up" and "Num8" or "Num2")
  340.   end;
  341. }
  342.  
  343. Macro { description="luacheck: process current editor";
  344.   area="Editor";    key="CtrlShiftF7";  filemask="*.lua";
  345.   uid="CE634ECE-1039-43F3-80CC-8BB17B1FDB05";
  346.   action=Check;
  347. }

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Tue 21 Jun, 2016 15:10

Ни один из предложенных мной варианта в шапку пока не пойдёт, т.к. не соответствуют моему видению процесса отладки кода.
Ведь (в идеале) требуется избавиться от всех предупреждений.

Замечу, что изменение кода это не единственный путь "избавления".
Luacheck всего лишь предупреждает, и если какой-то приём в коде использован сознательно, то можно просто подавить предупреждение, например с помощью inline-опций (есть и другие варианты, но не суть).

Впрочем, не исключаю, что действительно может есть смысл рассматривать различные группы предупреждений по отдельности.
Т.е. например:
- можно сортировать список не в порядке следования, а по кодам
- или как вы и предлагали фильтровать список, но тогда не только по "1", а и по прочим группам.

User avatar
HaRT
Moderator
Posts: 8118
Joined: Tue 30 Aug, 2005 17:21
Location: Санкт-Петербург
Has thanked: 68 times
Been thanked: 106 times

luacheck — статический анализатор для Lua

Post by HaRT » Tue 21 Jun, 2016 16:22

John Doe wrote: здесь просто скрывается всё что не начинается на "1", но зато список не закрывается
Спасибо, погоняю.
John Doe wrote: рассматривать различные группы предупреждений по отдельности
Мне вот тоже уже приходило в голову, что, возможно, имело бы смысл сопоставить каждому предупреждению тэги (хоть по тем же опциям luacheck), и фильтровать, включая/выключая те или иные тэги. Но я больших программ на Луа не пишу, поэтому не могу утверждать, как будет удобно при серьёзной разработке.
Фар есть инструмент, а не нянька. © 2009 DrKnS

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Tue 21 Jun, 2016 21:47

Заметил, что моя рабочая версия отличается от выложенной в шапке.
Изменения больше внутренние, но для порядка обновил.

IgorZ
Posts: 463
Joined: Wed 13 Jul, 2011 03:32
Has thanked: 6 times
Been thanked: 9 times

luacheck — статический анализатор для Lua

Post by IgorZ » Thu 28 Jul, 2016 05:37

Случайно заметил ошибку:

В обоих макросах uid="60596FEB-E7C5-47A5-A3C9-B782C8F8EF93"

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Thu 28 Jul, 2016 06:13

Я тоже нашёл её случайно, в процессе перехода на id )
Во втором будет id="CE634ECE-1039-43F3-80CC-8BB17B1FDB05";

Shmuel
Posts: 5230
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 16 times
Been thanked: 151 times

luacheck — статический анализатор для Lua

Post by Shmuel » Thu 28 Jul, 2016 06:15

Возможно LuaMacro должен это ловить и выдавать сообщения?

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Thu 28 Jul, 2016 06:23

Возможно, но позиция изложенная тут мне кажется обоснованной.
Если когда-нибудь в фаре появится окошко с логом, то там таким ошибком самое место.

А сейчас как вариант можно при обнаружении такой ошибки создавать в таблице макроса поле error = "duplicated id", а макробраузеры сделают остальное.

P.S.
В rebind есть возможность отлавливать такие ошибки, но если будет официальное поле error, то пожалуй тоже уберу.

User avatar
HaRT
Moderator
Posts: 8118
Joined: Tue 30 Aug, 2005 17:21
Location: Санкт-Петербург
Has thanked: 68 times
Been thanked: 106 times

luacheck — статический анализатор для Lua

Post by HaRT » Thu 28 Jul, 2016 11:38

John Doe wrote: можно при обнаружении такой ошибки создавать в таблице макроса поле error = "duplicated id", а макробраузеры сделают остальное.
Если уж что-то такое и делать, то я бы предложил что-то более структурное, чем одна строка. Как минимум нужен массив строк, т.к. ошибок в одном макросе может быть несколько. Далее, с каждой ошибкой может ассоциироваться позиция в коде, а то и две или три. Ещё, поскольку с макросами работают разные плагины/макросы, неплохо бы иметь возможность задать в отдельном поле „источник“ ошибки. Ну и так далее — одним словом, есть, что обдумать/обсудить.
Last edited by HaRT on Thu 01 Jan, 1970 01:00, edited 0 times in total.
Reason: Подчёркнуто главное
Фар есть инструмент, а не нянька. © 2009 DrKnS

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Thu 28 Jul, 2016 14:57

HaRT
Пока что формально это внутренняя приватная структура плагина, недокументированная и подверженная внезапным изменениям.
Можно долго обдумывать, а потом ничего этого так и не пригодится.

А можно долго не думать, а изменить значение на таблицу тогда, когда возникнет реальная необходимость.

Вместо error можно завести поле duplicated_id

User avatar
HaRT
Moderator
Posts: 8118
Joined: Tue 30 Aug, 2005 17:21
Location: Санкт-Петербург
Has thanked: 68 times
Been thanked: 106 times

luacheck — статический анализатор для Lua

Post by HaRT » Thu 28 Jul, 2016 15:49

John Doe wrote: формально это внутренняя приватная структура плагина, недокументированная и подверженная внезапным изменениям
Это вступает в противоречие с высказанным ранее:
John Doe wrote: макробраузеры сделают остальное
John Doe wrote: Вместо error можно завести поле duplicated_id
Ещё хуже, ибо это отдельное поле, заточенное под конкретную ошибку.
Фар есть инструмент, а не нянька. © 2009 DrKnS

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Thu 28 Jul, 2016 15:58

HaRT wrote: Это вступает в противоречие с высказанным ранее:
Не знаю насчёт противоречий, но дела обстоят именно так: структура лишь косвенно документирована, и отдельные её элементы могут меняться (и меняются) без предупреждения.

А макробраузеры приспосабливаются.

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Sun 28 Aug, 2016 21:17

1.3.0-beta: Поддержка moonscript
1.3.1-beta: С этим мунскриптом непросто всё
1.3.2-beta: Обработка синтаксических ошибок.

Update
Прогнал на исходном коде moonscript, по результатам кое-что исправил/усовершенствовал.
1.3.3 в шапке.

lysenkov
Posts: 2
Joined: Wed 15 Mar, 2017 18:50
Has thanked: 1 time

luacheck — статический анализатор для Lua

Post by lysenkov » Wed 15 Mar, 2017 18:52

Скажите, куда положить .luacheckrc, чтобы он загрузился?

User avatar
John Doe
Бюрократ
Posts: 11415
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

luacheck — статический анализатор для Lua

Post by John Doe » Sun 19 Mar, 2017 17:20

По замыслу он предполагается в текущей папке, или выше (вплоть до корня). В контексте фара это не очень надёжно, и я даже не проверял работает ли.
На практике конфигурацию можно задать прямо в luacheck_editor.lua, а если не хочется трогать исходник, то использовать возможности cfgscript.

User avatar
HaRT
Moderator
Posts: 8118
Joined: Tue 30 Aug, 2005 17:21
Location: Санкт-Петербург
Has thanked: 68 times
Been thanked: 106 times

luacheck — статический анализатор для Lua

Post by HaRT » Sun 19 Mar, 2017 21:02

John Doe wrote: По замыслу он предполагается в текущей папке, или выше (вплоть до корня). В контексте фара это не очень надёжно, и я даже не проверял работает ли.
Так может лучше от папки проверяемого файла?
Фар есть инструмент, а не нянька. © 2009 DrKnS

Post Reply

Return to “Обсуждение макросов”