From 2469dbae153066fad83edcced82f17aee77d0a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Mon, 11 Jul 2022 20:34:44 +0800 Subject: resolve #1029 treat _ENV = {} as local _ENV = {} local _ENV = nil will disable all globals local _ENV = {} will enable all globals local _ENV = {} ---@type mathlib will open globals in mathlib --- script/core/diagnostics/global-in-nil-env.lua | 68 +++++++------------------ script/core/diagnostics/undefined-env-child.lua | 32 +++++++++--- script/core/diagnostics/undefined-global.lua | 6 +-- script/parser/compile.lua | 11 +++- 4 files changed, 58 insertions(+), 59 deletions(-) (limited to 'script') diff --git a/script/core/diagnostics/global-in-nil-env.lua b/script/core/diagnostics/global-in-nil-env.lua index 334fd81a..e154080c 100644 --- a/script/core/diagnostics/global-in-nil-env.lua +++ b/script/core/diagnostics/global-in-nil-env.lua @@ -2,65 +2,35 @@ local files = require 'files' local guide = require 'parser.guide' local lang = require 'language' --- TODO: 检查路径是否可达 -local function mayRun(path) - return true -end - return function (uri, callback) - local ast = files.getState(uri) - if not ast then - return - end - local root = guide.getRoot(ast.ast) - local env = guide.getENV(root) - - local nilDefs = {} - if not env or not env.ref then - return - end - for _, ref in ipairs(env.ref) do - if ref.type == 'setlocal' then - if ref.value and ref.value.type == 'nil' then - nilDefs[#nilDefs+1] = ref - end - end - end - - if #nilDefs == 0 then + local state = files.getState(uri) + if not state then return end local function check(source) local node = source.node if node.tag == '_ENV' then - local ok - for _, nilDef in ipairs(nilDefs) do - local mode, pathA = guide.getPath(nilDef, source) - if mode == 'before' - and mayRun(pathA) then - ok = nilDef - break - end - end - if ok then - callback { - start = source.start, - finish = source.finish, - uri = uri, - message = lang.script.DIAG_GLOBAL_IN_NIL_ENV, - related = { - { - start = ok.start, - finish = ok.finish, - uri = uri, - } + return + end + + if not node.value or node.value.type == 'nil' then + callback { + start = source.start, + finish = source.finish, + uri = uri, + message = lang.script.DIAG_GLOBAL_IN_NIL_ENV, + related = { + { + start = node.start, + finish = node.finish, + uri = uri, } } - end + } end end - guide.eachSourceType(ast.ast, 'getglobal', check) - guide.eachSourceType(ast.ast, 'setglobal', check) + guide.eachSourceType(state.ast, 'getglobal', check) + guide.eachSourceType(state.ast, 'setglobal', check) end diff --git a/script/core/diagnostics/undefined-env-child.lua b/script/core/diagnostics/undefined-env-child.lua index 2f559697..1dff575b 100644 --- a/script/core/diagnostics/undefined-env-child.lua +++ b/script/core/diagnostics/undefined-env-child.lua @@ -3,20 +3,40 @@ local guide = require 'parser.guide' local lang = require 'language' local vm = require "vm.vm" +---@param source parser.object +---@return boolean +local function isBindDoc(source) + if not source.bindDocs then + return false + end + for _, doc in ipairs(source.bindDocs) do + if doc.type == 'doc.type' + or doc.type == 'doc.class' then + return true + end + end + return false +end + return function (uri, callback) - local ast = files.getState(uri) - if not ast then + local state = files.getState(uri) + if not state then return end - guide.eachSourceType(ast.ast, 'getglobal', function (source) - -- 单独验证自己是否在重载过的 _ENV 中有定义 + + guide.eachSourceType(state.ast, 'getglobal', function (source) if source.node.tag == '_ENV' then return end - local defs = vm.getDefs(source) - if #defs > 0 then + + if not isBindDoc(source.node) then return end + + if #vm.getDefs(source) > 0 then + return + end + local key = source[1] callback { start = source.start, diff --git a/script/core/diagnostics/undefined-global.lua b/script/core/diagnostics/undefined-global.lua index bf161c73..179c9204 100644 --- a/script/core/diagnostics/undefined-global.lua +++ b/script/core/diagnostics/undefined-global.lua @@ -15,8 +15,8 @@ local requireLike = { ---@async return function (uri, callback) - local ast = files.getState(uri) - if not ast then + local state = files.getState(uri) + if not state then return end @@ -25,7 +25,7 @@ return function (uri, callback) local cache = {} -- 遍历全局变量,检查所有没有 set 模式的全局变量 - guide.eachSourceType(ast.ast, 'getglobal', function (src) ---@async + guide.eachSourceType(state.ast, 'getglobal', function (src) ---@async local key = src[1] if not key then return diff --git a/script/parser/compile.lua b/script/parser/compile.lua index bae1e21a..e396cb21 100644 --- a/script/parser/compile.lua +++ b/script/parser/compile.lua @@ -2834,7 +2834,16 @@ local function compileExpAsAction(exp) pushActionIntoCurrentChunk(exp) if GetToSetMap[exp.type] then skipSpace() - local action, isSet = parseMultiVars(exp, parseExp) + local isLocal + if exp.type == 'getlocal' and exp[1] == State.ENVMode then + exp.special = nil + local loc = createLocal(exp, parseLocalAttrs()) + loc.locPos = exp.start + loc.effect = maxinteger + isLocal = true + skipSpace() + end + local action, isSet = parseMultiVars(exp, parseExp, isLocal) if isSet or action.type == 'getmethod' then return action -- cgit v1.2.3