summaryrefslogtreecommitdiffstats
path: root/autoload/dart.vim
blob: 76013172d941aa7557b66602bafa68ca741a505d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'dart') == -1
  

function! s:error(text) abort
  echohl Error
  echomsg printf('[dart-vim-plugin] %s', a:text)
  echohl None
endfunction

function! s:cexpr(errorformat, joined_lines) abort
  let temp_errorfomat = &errorformat
  try
    let &errorformat = a:errorformat
    cexpr a:joined_lines
    copen
  finally
    let &errorformat = temp_errorfomat
  endtry
endfunction

function! dart#fmt(q_args) abort
  if executable('dartfmt')
    let buffer_content = join(getline(1, '$'), "\n")
    let joined_lines = system(printf('dartfmt %s', a:q_args), buffer_content)
    if 0 == v:shell_error
      let win_view = winsaveview()
      let lines = split(joined_lines, "\n")
      silent keepjumps call setline(1, lines)
      if line('$') > len(lines)
        silent keepjumps execute string(len(lines)+1).',$ delete'
      endif
      call winrestview(win_view)
    else
      let errors = split(joined_lines, "\n")[2:]
      let file_path = expand('%')
      call map(errors, 'file_path.":".v:val')
      let error_format = '%A%f:line %l\, column %c of stdin: %m,%C%.%#'
      call s:cexpr(error_format, join(errors, "\n"))
    endif
  else
    call s:error('cannot execute binary file: dartfmt')
  endif
endfunction

function! dart#analyzer(q_args) abort
  if executable('dartanalyzer')
    let path = expand('%:p:gs:\:/:')
    if filereadable(path)
      let joined_lines = system(printf('dartanalyzer %s %s', a:q_args, shellescape(path)))
      call s:cexpr('%m (%f\, line %l\, col %c)', joined_lines)
    else
      call s:error(printf('cannot read a file: "%s"', path))
    endif
  else
    call s:error('cannot execute binary file: dartanalyzer')
  endif
endfunction

function! dart#tojs(q_args) abort
  if executable('dart2js')
    let path = expand('%:p:gs:\:/:')
    if filereadable(path)
      let joined_lines = system(printf('dart2js %s %s', a:q_args, shellescape(path)))
      call s:cexpr('%m (%f\, line %l\, col %c)', joined_lines)
    else
      call s:error(printf('cannot read a file: "%s"', path))
    endif
  else
    call s:error('cannot execute binary file: dartanalyzer')
  endif
endfunction

" Finds the path to `uri`.
"
" If the file is a package: uri, looks for a .packages file to resolve the path.
" If the path cannot be resolved, or is not a package: uri, returns the
" original.
function! dart#resolveUri(uri) abort
  if a:uri !~ 'package:'
    return a:uri
  endif
  let package_name = substitute(a:uri, 'package:\(\w\+\)\/.*', '\1', '')
  let [found, package_map] = s:PackageMap()
  if !found
    call s:error('cannot find .packages file')
    return a:uri
  endif
  if !has_key(package_map, package_name)
    call s:error('no package mapping for '.package_name)
    return a:uri
  endif
  let package_lib = package_map[package_name]
  return substitute(a:uri,
      \ 'package:'.package_name,
      \ escape(package_map[package_name], '\'),
      \ '')
endfunction

" A map from package name to lib directory parse from a '.packages' file.
"
" Returns [found, package_map]
function! s:PackageMap() abort
  let [found, dot_packages] = s:DotPackagesFile()
  if !found
    return [v:false, {}]
  endif
  let dot_packages_dir = fnamemodify(dot_packages, ':p:h')
  let lines = readfile(dot_packages)
  let map = {}
  for line in lines
    if line =~ '\s*#'
      continue
    endif
    let package = substitute(line, ':.*$', '', '')
    let lib_dir = substitute(line, '^[^:]*:', '', '')
    if lib_dir =~ 'file:/'
      let lib_dir = substitute(lib_dir, 'file://', '', '')
      if lib_dir =~ '/[A-Z]:/'
        let lib_dir = lib_dir[1:]
      endif
    else
      let lib_dir = resolve(dot_packages_dir.'/'.lib_dir)
    endif
    if lib_dir =~ '/$'
      let lib_dir = lib_dir[:len(lib_dir) - 2]
    endif
    let map[package] = lib_dir
  endfor
  return [v:true, map]
endfunction

" Finds a file name '.packages' in the cwd, or in any directory above the open
" file.
"
" Returns [found, file].
function! s:DotPackagesFile() abort
  if filereadable('.packages')
    return [v:true, '.packages']
  endif
  let dir_path = expand('%:p:h')
  while v:true
    let file_path = dir_path.'/.packages'
    if filereadable(file_path)
      return [v:true, file_path]
    endif
    let parent = fnamemodify(dir_path, ':h')
    if dir_path == parent
      break
    endif
    let dir_path = parent
  endwhile
  return [v:false, '']
endfunction

endif