Skip to content

Add Vim9Script support#205

Open
sideshowbarker wants to merge 1 commit into
vim-jp:masterfrom
sideshowbarker:vim9script-support
Open

Add Vim9Script support#205
sideshowbarker wants to merge 1 commit into
vim-jp:masterfrom
sideshowbarker:vim9script-support

Conversation

@sideshowbarker
Copy link
Copy Markdown

@sideshowbarker sideshowbarker commented Feb 12, 2026

Summary

  • Parse core Vim9Script constructs into proper AST nodes instead of routing them through parse_cmd_common, so downstream tools can analyze Vim9Script code without errors
  • Add # comment support when vim9script mode is active
  • Fix JS transpiler compile_let heuristic that incorrectly added var prefix to subscript assignments like named[pname] = 1

Motivation

Tools that depend on vim-vimlparser — such as vint and vim-language-server (which vendors the JS output directly) — report unexpected errors on valid Vim9Script code because the parser doesn't recognize constructs like def, typed parameters, or # comments. This adds structured parsing for the core Vim9Script syntax so these tools can handle Vim9Script files correctly.

Details

  • New node types: NODE_VIM9SCRIPT, NODE_DEF, NODE_ENDDEF, NODE_VAR, NODE_FINAL, NODE_EXPORT, NODE_IMPORT.

  • vim9script — sets a mode flag that enables # comments throughout the parser (in parse_one_cmd, parse_command, parse_comment, parse_trail, ends_excmds, separate_nextcmd).

  • def/enddef — parses typed parameters (name: type), default values (name: type = expr), variadic params (...name: type), and return type annotations (: returntype). Reads parameter names directly from the reader rather than using ExprTokenizer, since : is a valid name character in VimL identifiers and would cause x: to be tokenized as a single identifier.

  • var/final — parses variable declarations with optional type annotations. Same direct-reader approach to avoid the : tokenization issue.

  • export — wraps the inner command (def, var, etc.) by delegating to find_command + _parse_command, then moving the resulting nodes into the export node's body.

  • import — captures the import specification as a string.

Fixes #194

Parse core Vim9Script constructs into proper AST nodes so that
downstream tools can analyze Vim9Script code without errors.

New node types: NODE_VIM9SCRIPT, NODE_DEF, NODE_ENDDEF, NODE_VAR,
NODE_FINAL, NODE_EXPORT, NODE_IMPORT.

Parsers for vim9script, def/enddef (with typed parameters, return
types, default values, variadics), var/final (with type annotations),
export (wrapping inner commands), and import.

The # comment syntax is supported when vim9script mode is active.

Also fix JS transpiler heuristic for subscript assignments in
compile_let to check for [ in addition to . when deciding whether
to add var prefix.

Fixes vim-jp#194
@sideshowbarker
Copy link
Copy Markdown
Author

I started on this before seeing #204. The approach in that PR is clearly a much better solution than this. (I hadn’t even known yet about https://github.com/vim-jp/vim-vim9parser.) But I figured I’d go ahead and raise this anyway — in case it happens to be of any interest, or might be a possible interim solution until #204 gets merged.

mmrwoods added a commit to mmrwoods/vim-language-server that referenced this pull request Apr 9, 2026
From a fork of vimlparser that adds basic support for vim9script
See vim-jp/vim-vimlparser#205
And https://github.com/sideshowbarker/vim-vimlparser/tree/vim9script-support

While not perfect, this is a great improvement, thanks @sideshowbarker

A more comprehensive solution is under development, but not yet ready
See vim-jp/vim-vimlparser#204
And https://github.com/vim-jp/vim-vim9parser
mmrwoods added a commit to mmrwoods/vim-language-server that referenced this pull request Apr 13, 2026
From a fork of vimlparser that adds basic support for vim9script
See vim-jp/vim-vimlparser#205
And https://github.com/sideshowbarker/vim-vimlparser/tree/vim9script-support

While not perfect, this is a great improvement, thanks @sideshowbarker

A more comprehensive solution is under development, but not yet ready
See vim-jp/vim-vimlparser#204
And https://github.com/vim-jp/vim-vim9parser
@jclsn
Copy link
Copy Markdown

jclsn commented May 13, 2026

@ynkdir @mattn Can you please have a look at this? The vim9script support would be of a great help! There is a new language server written in it and it would be easier to develop, if there was proper LSP support!

Comment thread autoload/vimlparser.vim
Comment on lines +435 to +436
" VAR .ea .op .left .list .rest .right .type
" FINAL .ea .op .left .list .rest .right .type
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.type_str ?

Comment thread autoload/vimlparser.vim
" HEREDOC .rlist .op .body
" DEF .ea .body .left .rlist .default_args .attr .enddef
" ENDDEF .ea
" VAR .ea .op .left .list .rest .right .type
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.type_str

Comment thread autoload/vimlparser.vim
if self.reader.peekn(1) ==# ':'
call self.reader.getn(1)
call self.reader.skip_white()
call self.read_type()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return value unused

Comment thread autoload/vimlparser.vim
if self.reader.peekn(3) ==# '...'
call self.reader.getn(3)
call self.reader.skip_white()
let vname = self.reader.read_alpha()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vname should accept number letter or _

Comment thread autoload/vimlparser.vim
\ || self.reader.getpos() !=# self.ea.argpos)
\ && (self.ea.cmd.name !=# 'redir'
\ || self.reader.getpos().i !=# self.ea.argpos.i + 1 || pc !=# '@'))
\ || (self.vim9script && c ==# '#' && self.ea.cmd.flags !~# '\<NOTRLCOM\>')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vim 9 supports inline suffix comments, but it must place a space immediately before the comment character.

Comment thread autoload/vimlparser.vim
let node.str = ''
call self.reader.skip_white()
" Read the rest of the import line as a string (import autoload 'path' or import 'path' as Name)
let node.str = self.reader.getn(-1)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import './x.vim' as util # comment

comment strings are included.

Comment thread autoload/vimlparser.vim
let left = '(' . left . ')'
endif
let right = self.compile(a:node.right)
call self.out('(var %s %s %s)', a:node.op, left, right)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type name is lost. (type_str should have)

Comment thread autoload/vimlparser.vim
let left = '(' . left . ')'
endif
let right = self.compile(a:node.right)
call self.out('(final %s %s %s)', a:node.op, left, right)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type name is lost. (type_str should have)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vim9 script support?

3 participants