1
0
forked from aniani/vim

patch 9.1.1307: make syntax does not reliably detect different flavors

Problem:  GNU extensions, such as `ifeq` and `wildcard` function, are
          highlighted in BSDmakefile
Solution: detect BSD, GNU, or Microsoft implementation according to
	  filename, user-defined global variables, or file contents

closes: #17089

Co-authored-by: Roland Hieber <rohieb@users.noreply.github.com>
Signed-off-by: Eisuke Kawashima <e-kwsm@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Eisuke Kawashima 2025-04-15 19:20:06 +02:00 committed by Christian Brabandt
parent 32f2bb6e1e
commit f35bd76b31
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
7 changed files with 126 additions and 28 deletions

View File

@ -557,17 +557,47 @@ export def FTm()
enddef enddef
export def FTmake() export def FTmake()
# Check if it is a Microsoft Makefile # Check if it is a BSD, GNU, or Microsoft Makefile
unlet! b:make_microsoft unlet! b:make_flavor
# 1. filename
if expand('%:t') == 'BSDmakefile'
b:make_flavor = 'bsd'
setf make
return
elseif expand('%:t') == 'GNUmakefile'
b:make_flavor = 'gnu'
setf make
return
endif
# 2. user's setting
if exists('g:make_flavor')
b:make_flavor = g:make_flavor
setf make
return
elseif get(g:, 'make_microsoft')
echom "make_microsoft is deprecated; try g:make_flavor = 'microsoft' instead"
b:make_flavor = 'microsoft'
setf make
return
endif
# 3. try to detect a flavor from file content
var n = 1 var n = 1
while n < 1000 && n <= line('$') while n < 1000 && n <= line('$')
var line = getline(n) var line = getline(n)
if line =~? '^\s*!\s*\(ifn\=\(def\)\=\|include\|message\|error\)\>' if line =~? '^\s*!\s*\(ifn\=\(def\)\=\|include\|message\|error\)\>'
b:make_microsoft = 1 b:make_flavor = 'microsoft'
break break
elseif line =~ '^ *ifn\=\(eq\|def\)\>' || line =~ '^ *[-s]\=include\s' elseif line =~ '^\.\%(export\|error\|for\|if\%(n\=\%(def\|make\)\)\=\|info\|warning\)\>'
b:make_flavor = 'bsd'
break break
elseif line =~ '^ *\w\+\s*[!?:+]=' elseif line =~ '^ *\%(ifn\=\%(eq\|def\)\|define\|override\)\>'
b:make_flavor = 'gnu'
break
elseif line =~ '\$[({][a-z-]\+\s\+\S\+' # a function call, e.g. $(shell pwd)
b:make_flavor = 'gnu'
break break
endif endif
n += 1 n += 1

View File

@ -1,4 +1,4 @@
*filetype.txt* For Vim version 9.1. Last change: 2025 Mar 15 *filetype.txt* For Vim version 9.1. Last change: 2025 Apr 15
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -158,6 +158,8 @@ variables can be used to overrule the filetype used for certain extensions:
*.inc g:filetype_inc *.inc g:filetype_inc
*.lsl g:filetype_lsl *.lsl g:filetype_lsl
*.m g:filetype_m |ft-mathematica-syntax| *.m g:filetype_m |ft-mathematica-syntax|
*[mM]makefile,*.mk,*.mak,[mM]akefile*
g:make_flavor |ft-make-syntax|
*.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md *.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md
g:filetype_md |ft-pandoc-syntax| g:filetype_md |ft-pandoc-syntax|
*.mod g:filetype_mod *.mod g:filetype_mod

View File

@ -1,4 +1,4 @@
*syntax.txt* For Vim version 9.1. Last change: 2025 Apr 13 *syntax.txt* For Vim version 9.1. Last change: 2025 Apr 15
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -2393,11 +2393,16 @@ Comments are also highlighted by default. You can turn this off by using: >
:let make_no_comments = 1 :let make_no_comments = 1
Microsoft Makefile handles variable expansion and comments differently There are various Make implementations, which add extensions other than the
(backslashes are not used for escape). If you see any wrong highlights POSIX specification and thus are mutually incompatible. If the filename is
because of this, you can try this: > BSDmakefile or GNUmakefile, the corresponding implementation is automatically
determined; otherwise vim tries to detect it by the file contents. If you see
any wrong highlights because of this, you can enforce a flavor by setting one
of the following: >
:let make_microsoft = 1 :let g:make_flavor = 'bsd' " or
:let g:make_flavor = 'gnu' " or
:let g:make_flavor = 'microsoft'
MAPLE *maple.vim* *ft-maple-syntax* MAPLE *maple.vim* *ft-maple-syntax*

View File

@ -3186,7 +3186,7 @@ au BufNewFile,BufRead */etc/sensors.d/[^.]* call s:StarSetf('sensors')
au BufNewFile,BufRead */etc/logcheck/*.d*/* call s:StarSetf('logcheck') au BufNewFile,BufRead */etc/logcheck/*.d*/* call s:StarSetf('logcheck')
" Makefile " Makefile
au BufNewFile,BufRead [mM]akefile* call s:StarSetf('make') au BufNewFile,BufRead [mM]akefile* if expand('<afile>:t') !~ g:ft_ignore_pat | call dist#ft#FTmake() | endif
" Ruby Makefile " Ruby Makefile
au BufNewFile,BufRead [rR]akefile* call s:StarSetf('ruby') au BufNewFile,BufRead [rR]akefile* call s:StarSetf('ruby')

View File

@ -4,6 +4,7 @@
" Previous Maintainer: Claudio Fleiner <claudio@fleiner.com> " Previous Maintainer: Claudio Fleiner <claudio@fleiner.com>
" URL: https://github.com/vim/vim/blob/master/runtime/syntax/make.vim " URL: https://github.com/vim/vim/blob/master/runtime/syntax/make.vim
" Last Change: 2022 Nov 06 " Last Change: 2022 Nov 06
" 2025 Apr 15 by Vim project: rework Make flavor detection (#17089)
" quit when a syntax file was already loaded " quit when a syntax file was already loaded
if exists("b:current_syntax") if exists("b:current_syntax")
@ -13,6 +14,9 @@ endif
let s:cpo_save = &cpo let s:cpo_save = &cpo
set cpo&vim set cpo&vim
" enable GNU extension when b:make_flavor is not set—detection failed or Makefile is POSIX-compliant
let s:make_flavor = 'gnu'
" some special characters " some special characters
syn match makeSpecial "^\s*[@+-]\+" syn match makeSpecial "^\s*[@+-]\+"
syn match makeNextLine "\\\n\s*" syn match makeNextLine "\\\n\s*"
@ -21,14 +25,16 @@ syn match makeNextLine "\\\n\s*"
syn region makeDefine start="^\s*define\s" end="^\s*endef\s*\(#.*\)\?$" syn region makeDefine start="^\s*define\s" end="^\s*endef\s*\(#.*\)\?$"
\ contains=makeStatement,makeIdent,makePreCondit,makeDefine \ contains=makeStatement,makeIdent,makePreCondit,makeDefine
" Microsoft Makefile specials if get(b:, 'make_flavor', s:make_flavor) == 'microsoft'
syn case ignore " Microsoft Makefile specials
syn match makeInclude "^!\s*include\s.*$" syn case ignore
syn match makePreCondit "^!\s*\(cmdswitches\|error\|message\|include\|if\|ifdef\|ifndef\|else\|else\s*if\|else\s*ifdef\|else\s*ifndef\|endif\|undef\)\>" syn match makeInclude "^!\s*include\s.*$"
syn case match syn match makePreCondit "^!\s*\(cmdswitches\|error\|message\|include\|if\|ifdef\|ifndef\|else\|else\s*if\|else\s*ifdef\|else\s*ifndef\|endif\|undef\)\>"
syn case match
endif
" identifiers " identifiers
if exists("b:make_microsoft") || exists("make_microsoft") if get(b:, 'make_flavor', s:make_flavor) == 'microsoft'
syn region makeIdent start="\$(" end=")" contains=makeStatement,makeIdent syn region makeIdent start="\$(" end=")" contains=makeStatement,makeIdent
syn region makeIdent start="\${" end="}" contains=makeStatement,makeIdent syn region makeIdent start="\${" end="}" contains=makeStatement,makeIdent
else else
@ -59,13 +65,31 @@ syn match makeTarget "^[~A-Za-z0-9_./$(){}%*@-][A-Za-z0-9_./\t $(){}%*
\ skipnl nextgroup=makeCommands,makeCommandError \ skipnl nextgroup=makeCommands,makeCommandError
syn region makeSpecTarget transparent matchgroup=makeSpecTarget syn region makeSpecTarget transparent matchgroup=makeSpecTarget
\ start="^\.\(SUFFIXES\|PHONY\|DEFAULT\|PRECIOUS\|IGNORE\|SILENT\|EXPORT_ALL_VARIABLES\|KEEP_STATE\|LIBPATTERNS\|NOTPARALLEL\|DELETE_ON_ERROR\|INTERMEDIATE\|POSIX\|SECONDARY\|ONESHELL\)\>\s*:\{1,2}[^:=]"rs=e-1 \ start="^\.\(SUFFIXES\|PHONY\|DEFAULT\|PRECIOUS\|IGNORE\|SILENT\|NOTPARALLEL\|POSIX\)\>\s*:\{1,2}[^:=]"rs=e-1
\ end="[^\\]$" keepend \ end="[^\\]$" keepend
\ contains=makeIdent,makeSpecTarget,makeNextLine,makeComment skipnl nextGroup=makeCommands \ contains=makeIdent,makeSpecTarget,makeNextLine,makeComment skipnl nextGroup=makeCommands
syn match makeSpecTarget "^\.\(SUFFIXES\|PHONY\|DEFAULT\|PRECIOUS\|IGNORE\|SILENT\|EXPORT_ALL_VARIABLES\|KEEP_STATE\|LIBPATTERNS\|NOTPARALLEL\|DELETE_ON_ERROR\|INTERMEDIATE\|POSIX\|SECONDARY\|ONESHELL\)\>\s*::\=\s*$" syn match makeSpecTarget "^\.\(SUFFIXES\|PHONY\|DEFAULT\|PRECIOUS\|IGNORE\|SILENT\|NOTPARALLEL\|POSIX\)\>\s*::\=\s*$"
\ contains=makeIdent,makeComment \ contains=makeIdent,makeComment
\ skipnl nextgroup=makeCommands,makeCommandError \ skipnl nextgroup=makeCommands,makeCommandError
if get(b:, 'make_flavor', s:make_flavor) == 'bsd'
syn region makeSpecTarget transparent matchgroup=makeSpecTarget
\ start="^\.DELETE_ON_ERROR\>\s*:\{1,2}[^:=]"rs=e-1
\ end="[^\\]$" keepend
\ contains=makeIdent,makeSpecTarget,makeNextLine,makeComment skipnl nextGroup=makeCommands
syn match makeSpecTarget "^\.DELETE_ON_ERROR\>\s*::\=\s*$"
\ contains=makeIdent,makeComment
\ skipnl nextgroup=makeCommands,makeCommandError
elseif get(b:, 'make_flavor', s:make_flavor) == 'gnu'
syn region makeSpecTarget transparent matchgroup=makeSpecTarget
\ start="^\.\(EXPORT_ALL_VARIABLES\|DELETE_ON_ERROR\|INTERMEDIATE\|KEEP_STATE\|LIBPATTERNS\|ONESHELL\|SECONDARY\)\>\s*:\{1,2}[^:=]"rs=e-1
\ end="[^\\]$" keepend
\ contains=makeIdent,makeSpecTarget,makeNextLine,makeComment skipnl nextGroup=makeCommands
syn match makeSpecTarget "^\.\(EXPORT_ALL_VARIABLES\|DELETE_ON_ERROR\|INTERMEDIATE\|KEEP_STATE\|LIBPATTERNS\|ONESHELL\|SECONDARY\)\>\s*::\=\s*$"
\ contains=makeIdent,makeComment
\ skipnl nextgroup=makeCommands,makeCommandError
endif
syn match makeCommandError "^\s\+\S.*" contained syn match makeCommandError "^\s\+\S.*" contained
syn region makeCommands contained start=";"hs=s+1 start="^\t" syn region makeCommands contained start=";"hs=s+1 start="^\t"
\ end="^[^\t#]"me=e-1,re=e-1 end="^$" \ end="^[^\t#]"me=e-1,re=e-1 end="^$"
@ -74,17 +98,19 @@ syn region makeCommands contained start=";"hs=s+1 start="^\t"
syn match makeCmdNextLine "\\\n."he=e-1 contained syn match makeCmdNextLine "\\\n."he=e-1 contained
" some directives " some directives
syn match makePreCondit "^ *\(ifn\=\(eq\|def\)\>\|else\(\s\+ifn\=\(eq\|def\)\)\=\>\|endif\>\)"
syn match makeInclude "^ *[-s]\=include\s.*$" syn match makeInclude "^ *[-s]\=include\s.*$"
syn match makeStatement "^ *vpath"
syn match makeExport "^ *\(export\|unexport\)\>" syn match makeExport "^ *\(export\|unexport\)\>"
syn match makeOverride "^ *override\>" if get(b:, 'make_flavor', s:make_flavor) == 'gnu'
" Statements / Functions (GNU make) " Statements / Functions (GNU make)
syn match makeStatement contained "(\(abspath\|addprefix\|addsuffix\|and\|basename\|call\|dir\|error\|eval\|file\|filter-out\|filter\|findstring\|firstword\|flavor\|foreach\|guile\|if\|info\|join\|lastword\|notdir\|or\|origin\|patsubst\|realpath\|shell\|sort\|strip\|subst\|suffix\|value\|warning\|wildcard\|word\|wordlist\|words\)\>"ms=s+1 syn match makePreCondit "^ *\(ifn\=\(eq\|def\)\>\|else\(\s\+ifn\=\(eq\|def\)\)\=\>\|endif\>\)"
syn match makeStatement "^ *vpath\>"
syn match makeOverride "^ *override\>"
syn match makeStatement contained "[({]\(abspath\|addprefix\|addsuffix\|and\|basename\|call\|dir\|error\|eval\|file\|filter-out\|filter\|findstring\|firstword\|flavor\|foreach\|guile\|if\|info\|intcmp\|join\|lastword\|let\|notdir\|or\|origin\|patsubst\|realpath\|shell\|sort\|strip\|subst\|suffix\|value\|warning\|wildcard\|word\|wordlist\|words\)\>"ms=s+1
endif
" Comment " Comment
if !exists("make_no_comments") if !exists("make_no_comments")
if exists("b:make_microsoft") || exists("make_microsoft") if get(b:, 'make_flavor', s:make_flavor) == 'microsoft'
syn match makeComment "#.*" contains=@Spell,makeTodo syn match makeComment "#.*" contains=@Spell,makeTodo
else else
syn region makeComment start="#" end="^$" end="[^\\]$" keepend contains=@Spell,makeTodo syn region makeComment start="#" end="^$" end="[^\\]$" keepend contains=@Spell,makeTodo

View File

@ -2857,15 +2857,48 @@ endfunc
func Test_make_file() func Test_make_file()
filetype on filetype on
" BSD Makefile
call writefile([''], 'BSDmakefile', 'D')
split BSDmakefile
call assert_equal('bsd', get(b:, 'make_flavor', ''))
bwipe!
call writefile(['.ifmake all', '.endif'], 'XMakefile.mak', 'D')
split XMakefile.mak
call assert_equal('bsd', get(b:, 'make_flavor', ''))
bwipe!
" GNU Makefile
call writefile([''], 'GNUmakefile', 'D')
split GNUmakefile
call assert_equal('gnu', get(b:, 'make_flavor', ''))
bwipe!
call writefile(['ifeq ($(foo),foo)', 'endif'], 'XMakefile.mak', 'D')
split XMakefile.mak
call assert_equal('gnu', get(b:, 'make_flavor', ''))
bwipe!
call writefile(['define foo', 'endef'], 'XMakefile.mak', 'D')
split XMakefile.mak
call assert_equal('gnu', get(b:, 'make_flavor', ''))
bwipe!
call writefile(['vim := $(wildcard *.vim)'], 'XMakefile.mak', 'D')
split XMakefile.mak
call assert_equal('gnu', get(b:, 'make_flavor', ''))
bwipe!
" Microsoft Makefile " Microsoft Makefile
call writefile(['# Makefile for Windows', '!if "$(VIMDLL)" == "yes"'], 'XMakefile.mak', 'D') call writefile(['# Makefile for Windows', '!if "$(VIMDLL)" == "yes"'], 'XMakefile.mak', 'D')
split XMakefile.mak split XMakefile.mak
call assert_equal(1, get(b:, 'make_microsoft', 0)) call assert_equal('microsoft', get(b:, 'make_flavor', ''))
bwipe! bwipe!
" BSD or GNU
call writefile(['# get the list of tests', 'include testdir/Make_all.mak'], 'XMakefile.mak', 'D') call writefile(['# get the list of tests', 'include testdir/Make_all.mak'], 'XMakefile.mak', 'D')
split XMakefile.mak split XMakefile.mak
call assert_equal(0, get(b:, 'make_microsoft', 0)) call assert_notequal('microsoft', get(b:, 'make_flavor', ''))
bwipe! bwipe!
filetype off filetype off

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1307,
/**/ /**/
1306, 1306,
/**/ /**/