ZyX_I avatar ZyX_I committed b1df018

@/functions: Added support for nested 3-tuple function definitions
Made it get plugdict for the decorator from plugin that requested
decorator
Fixed error messages

Comments (0)

Files changed (3)

autoload/frawor/functions.vim

                 \                'не является строкой',
                 \       '1nver': 'второй элемент «function» должен быть '.
                 \                'списком неотрицательных целых чисел',
+                \       'nodep': 'дополнение %s должно зависеть от @/functions',
+                \       'nofun': 'не найдена функция %s в s:_aufunctions '.
+                \                'дополнения %s',
                 \   'invdecret': 'декоратор %s вернул неверное значение',
                 \     'decndep': 'дополнение, определившее декоратор %s, '.
                 \                'не находится в списке зависимостей',
                 \       '1nver': 'second element of `function'' key must be '.
                 \                'a list of non-negative integers',
                 \       'nodep': 'plugin %s must depend on @/functions',
-                \       'nodep': 'no function %s in s:_aufunctions of %s',
+                \       'nofun': 'no function %s in s:_aufunctions of %s',
                 \   'invdecret': 'decorator %s returned invalid value',
                 \     'decndep': 'plugin that defined decorator %s '.
                 \                'is not in dependency list',
 endfunction
 "▶1 fundef          :: plugdict, funopts, fundef, fname → Funcref
 function s:F.fundef(plugdict, funopts, fundef, fname)
+    "▶2 Check funopts
+    if !has_key(a:funopts, 'function')
+        call s:_f.throw('nofunc', a:fname, a:plugdict.id)
+    elseif type(a:funopts.function)!=2 && type(a:funopts.function)!=type([])
+        call s:_f.throw('nref', a:fname, a:plugdict.id, 'function')
+    elseif !empty(filter(keys(a:funopts), 'v:val isnot# "function" && '.
+                \                         'v:val isnot# "redefine" && '.
+                \                         'v:val[0] isnot# "@"'))
+        call s:_f.throw('invkeys', a:fname, a:plugdict.id)
+    endif
+    "▲2
+    " TODO: test nested 3-tuple function definitions and redefine key
     let fundefext=copy(a:funopts)
+    let decdeps={}
+    call map(keys(a:funopts), 'v:val[0] is# "@" ? '.
+                \               'extend(decdeps, {v:val[1:] : a:plugdict}) : 0')
     if type(a:funopts.function)==type([])
         if len(a:funopts.function)!=3
             call s:_f.throw('n3len', a:fname, a:plugdict.id)
             call s:_f.throw('nofun', a:fname, a:plugdict.id,
                         \   a:funopts.function[2], a:funopts.function[0])
         endif
-        call extend(fundefext, s:aufunctions[a:funopts.function[0]].functions)
+        let funopts=s:aufunctions[a:funopts.function[0]].functions
+        let fundefext=s:F.fundef(s:aufunctions[a:funopts.function[0]].plugdict,
+                    \            funopts, fundefext, a:fname)
+        call extend(decdeps, fundefext.decdeps)
         let sid=s:aufunctions[a:funopts.function[0]].sid
     else
         let sid=a:plugdict.sid
     endif
     let fundefext.function=s:F.refref(sid, fundefext.function)
-    call extend(a:fundef, fundefext, 'keep')
+    call extend(a:fundef, fundefext)
+    let a:fundef.decdeps=decdeps
     return a:fundef
 endfunction
 "▶1 delfunction     :: sid, Funcref → + :delfunction
 let s:nargsexpr=substitute(s:mapexpr, 'v:val', 'newargs', '')
 unlet s:subs
 function s:F.wrapfunc(plugdict, funopts, fundictsname, fname)
-    "▶2 Check a:funopts
-    if !has_key(a:funopts, 'function')
-        call s:_f.throw('nofunc', a:fname, a:plugdict.id)
-    elseif type(a:funopts.function)!=2 && type(a:funopts.function)!=type([])
-        call s:_f.throw('nref', a:fname, a:plugdict.id, 'function')
-    endif
-    "▲2
     let fname=a:fname
     let fdicts=s:{a:fundictsname}
     let fundef =  {'id': printf('%x', fdicts.nextid),
         let addedrval=0
         "▲2
         for decorator in decs
+            let decplugdict=fundef.decdeps[decorator.id]
             "▶2 Check existance of decorator definer in dependencies
-            if !has_key(a:plugdict.dependencies, decorator.plid)
+            if !has_key(decplugdict.dependencies, decorator.plid)
                 call s:_f.throw('decndep', a:fname, a:plugdict.id,
                             \              decorator.id)
             endif
             "▲2
-            call add(fblocks, decorator.func(a:plugdict, fname,
+            call add(fblocks, decorator.func(decplugdict, fname,
                         \                    a:funopts['@'.decorator.id]))
             "▶2 Check decorator return value
             if type(fblocks[-1])!=type([])
         let a:plugdict.g._aufunctions={}
     endif
     let s:aufunctions[a:plugdict.id]={'functions': a:plugdict.g._aufunctions,
-                \                     'sid': a:plugdict.sid}
+                \                     'sid': a:plugdict.sid,
+                \                     'plugdict': a:plugdict}
 endfunction
 call s:_f.newfeature('wrapfunc', {'cons': s:F.wrapfunc_cons,
             \                   'unload': s:F.delfunctions,
                    2. Dictionary {key} from |s:_aufunctions| dictionary of 
                       plugin with given {plid} is merged with the current 
                       dictionary, overriding keys in the latter. Load event of 
-                      |frawor-f-wrapfunc| feature is responsible for this.
-                                                        *frawor-fd-thisplugin*
-        thisplugin If this key is present, then plugin dictionary is taken 
-                   from the plugin that defined it last. Useful for decorators 
-                   in case |frawor-fd-function| contains a list.
+                      |frawor-f-wrapfunc| feature is responsible for this. 
+                      Nested loads are supported (i.e. when loaded function 
+                      description has similar 3-tuple).
+                      Note about merges: plugdict for decorator is taken from 
+                           the plugin that defined the decorator, not from the 
+                           plugin that created function definition. Same for 
+                           dependencies: plugin that defined the decorator 
+                           must be specified as the dependency of the plugin 
+                           that requested the decorator.
                                                           *frawor-fd-redefine*
         redefine   If this key is present, then it will try to redefine 
                    function if it exists, if it is not and function with given 

test/rtp/plugin/plugin-with-autoload-function.vim

+execute frawor#Setup('0.0', {'@/functions': '0.1',
+            \               '@/decorators': '0.0',
+            \'@plugin-with-autoload-function': '0.0'})
+function s:F.tracerun(plugdict, fname)
+    call WriteFile('In tracerun for '.a:fname)
+    return [0, '@@@', 0, ['try',
+                \           'call WriteFile("Calling '.a:fname.'")'],
+                \        ['finally',
+                \           'call WriteFile("Finished '.a:fname.'")',
+                \         'endtry'], 0]
+endfunction
+function s:F.func(...)
+    return a:0 == 1 ? a:1 : a:000
+endfunction
+call s:_f.adddecorator('tracerun', s:F.tracerun)
+let s:_autoload={
+            \'tracedfunc': {'function': s:F.func, '@tracerun': []},
+        \}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.