-
-
Notifications
You must be signed in to change notification settings - Fork 334
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2486 from fesily/plugin-OnNodeCompileFunctionParam
Plugin on node compile function param
- Loading branch information
Showing
6 changed files
with
245 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
local vm = require 'vm' | ||
local guide = require 'parser.guide' | ||
|
||
local _M = {} | ||
|
||
---@class node.match.pattern | ||
---@field next node.match.pattern? | ||
|
||
local function deepCompare(source, pattern) | ||
local type1, type2 = type(source), type(pattern) | ||
if type1 ~= type2 then | ||
return false | ||
end | ||
|
||
if type1 ~= "table" then | ||
return source == pattern | ||
end | ||
|
||
for key2, value2 in pairs(pattern) do | ||
local value1 = source[key2] | ||
if value1 == nil or not deepCompare(value1, value2) then | ||
return false | ||
end | ||
end | ||
|
||
return true | ||
end | ||
|
||
---@param source parser.object | ||
---@param pattern node.match.pattern | ||
---@return boolean | ||
function _M.matchPattern(source, pattern) | ||
if source.type == 'local' then | ||
if source.parent.type == 'funcargs' and source.parent.parent.type == 'function' then | ||
for i, ref in ipairs(source.ref) do | ||
if deepCompare(ref, pattern) then | ||
return true | ||
end | ||
end | ||
end | ||
end | ||
return false | ||
end | ||
|
||
local vaildVarRegex = "()([a-zA-Z][a-zA-Z0-9_]*)()" | ||
---创建类型 *.field.field形式的 pattern | ||
---@param pattern string | ||
---@return node.match.pattern?, string? | ||
function _M.createFieldPattern(pattern) | ||
local ret = { next = nil } | ||
local next = ret | ||
local init = 1 | ||
while true do | ||
local startpos, matched, endpos | ||
if pattern:sub(1, 1) == "*" then | ||
startpos, matched, endpos = init, "*", init + 1 | ||
else | ||
startpos, matched, endpos = vaildVarRegex:match(pattern, init) | ||
end | ||
if not startpos then | ||
break | ||
end | ||
if startpos ~= init then | ||
return nil, "invalid pattern" | ||
end | ||
local field = matched == "*" and { next = nil } | ||
or { field = { type = 'field', matched }, type = 'getfield', next = nil } | ||
next.next = field | ||
next = field | ||
pattern = pattern:sub(endpos) | ||
end | ||
return ret | ||
end | ||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
local files = require 'files' | ||
local scope = require 'workspace.scope' | ||
local nodeHelper = require 'plugins.nodeHelper' | ||
local vm = require 'vm' | ||
local guide = require 'parser.guide' | ||
|
||
|
||
local pattern, msg = nodeHelper.createFieldPattern("*.components") | ||
assert(pattern, msg) | ||
|
||
---@param source parser.object | ||
function OnCompileFunctionParam(next, func, source) | ||
if next(func, source) then | ||
return true | ||
end | ||
--从该参数的使用模式来推导该类型 | ||
if nodeHelper.matchPattern(source, pattern) then | ||
local type = vm.declareGlobal('type', 'TestClass', TESTURI) | ||
vm.setNode(source, vm.createNode(type, source)) | ||
return true | ||
end | ||
end | ||
|
||
local myplugin = { OnCompileFunctionParam = OnCompileFunctionParam } | ||
|
||
---@diagnostic disable: await-in-sync | ||
local function TestPlugin(script) | ||
local prefix = [[ | ||
---@class TestClass | ||
---@field b string | ||
]] | ||
---@param checker fun(state:parser.state) | ||
return function (plugin, checker) | ||
files.open(TESTURI) | ||
files.setText(TESTURI, prefix .. script, true) | ||
scope.getScope(TESTURI):set('pluginInterfaces', plugin) | ||
local state = files.getState(TESTURI) | ||
assert(state) | ||
checker(state) | ||
files.remove(TESTURI) | ||
end | ||
end | ||
|
||
TestPlugin [[ | ||
local function t(a) | ||
a.components:test() | ||
end | ||
]](myplugin, function (state) | ||
guide.eachSourceType(state.ast, 'local', function (src) | ||
if guide.getKeyName(src) == 'a' then | ||
local node = vm.compileNode(src) | ||
assert(node) | ||
assert(not vm.isUnknown(node)) | ||
end | ||
end) | ||
end) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
require 'plugins.ast.test' | ||
require 'plugins.ffi.test' | ||
require 'plugins.node.test' |