summaryrefslogtreecommitdiff
path: root/autoload/ale/statusline.vim
blob: 6b93ba5196f47c4b9598dc0a955fd7a7409c363a (plain)
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
" Author: KabbAmine <amine.kabb@gmail.com>
" Additions by: petpetpetpet <chris@freelanceninjas.com>
" Description: Statusline related function(s)

function! s:CreateCountDict() abort
    " Keys 0 and 1 are for backwards compatibility.
    " The count object used to be a List of [error_count, warning_count].
    return {
    \   '0': 0,
    \   '1': 0,
    \   'error': 0,
    \   'warning': 0,
    \   'info': 0,
    \   'style_error': 0,
    \   'style_warning': 0,
    \   'total': 0,
    \}
endfunction

" Update the buffer error/warning count with data from loclist.
function! ale#statusline#Update(buffer, loclist) abort
    if !exists('g:ale_buffer_info') || !has_key(g:ale_buffer_info, a:buffer)
        return
    endif

    let l:loclist = filter(copy(a:loclist), 'v:val.bufnr == a:buffer')
    let l:count = s:CreateCountDict()
    let l:count.total = len(l:loclist)

    " Allows easy access to the first instance of each problem type.
    let l:first_problems = {}

    for l:entry in l:loclist
        if l:entry.type is# 'W'
            if get(l:entry, 'sub_type', '') is# 'style'
                let l:count.style_warning += 1

                if l:count.style_warning == 1
                    let l:first_problems.style_warning = l:entry
                endif
            else
                let l:count.warning += 1

                if l:count.warning == 1
                    let l:first_problems.warning = l:entry
                endif
            endif
        elseif l:entry.type is# 'I'
            let l:count.info += 1

            if l:count.info == 1
                let l:first_problems.info = l:entry
            endif
        elseif get(l:entry, 'sub_type', '') is# 'style'
            let l:count.style_error += 1

            if l:count.style_error == 1
                let l:first_problems.style_error = l:entry
            endif
        else
            let l:count.error += 1

            if l:count.error == 1
                let l:first_problems.error = l:entry
            endif
        endif
    endfor

    " Set keys for backwards compatibility.
    let l:count[0] = l:count.error + l:count.style_error
    let l:count[1] = l:count.total - l:count[0]

    let g:ale_buffer_info[a:buffer].count = l:count
    let g:ale_buffer_info[a:buffer].first_problems = l:first_problems
endfunction

" Get the counts for the buffer, and update the counts if needed.
function! s:UpdateCacheIfNecessary(buffer) abort
    " Cache is cold, so manually ask for an update.
    if !has_key(g:ale_buffer_info[a:buffer], 'count')
        call ale#statusline#Update(
        \   a:buffer,
        \   g:ale_buffer_info[a:buffer].loclist
        \)
    endif
endfunction

function! s:BufferCacheExists(buffer) abort
    if !exists('g:ale_buffer_info') || !has_key(g:ale_buffer_info, a:buffer)
        return 0
    endif

    return 1
endfunction

" Get the counts for the buffer, and update the counts if needed.
function! s:GetCounts(buffer) abort
    if !s:BufferCacheExists(a:buffer)
        return s:CreateCountDict()
    endif

    call s:UpdateCacheIfNecessary(a:buffer)

    return g:ale_buffer_info[a:buffer].count
endfunction

" Get the dict of first_problems, update the buffer info cache if necessary.
function! s:GetFirstProblems(buffer) abort
    if !s:BufferCacheExists(a:buffer)
        return {}
    endif

    call s:UpdateCacheIfNecessary(a:buffer)

    return g:ale_buffer_info[a:buffer].first_problems
endfunction

" Returns a Dictionary with counts for use in third party integrations.
function! ale#statusline#Count(buffer) abort
    " The Dictionary is copied here before exposing it to other plugins.
    return copy(s:GetCounts(a:buffer))
endfunction

" Returns a copy of the *first* locline instance of the specified problem
" type. (so this would allow an external integration to know all the info
" about the first style warning in the file, for example.)
function! ale#statusline#FirstProblem(buffer, type) abort
    let l:first_problems = s:GetFirstProblems(a:buffer)

    if !empty(l:first_problems) && has_key(l:first_problems, a:type)
        return copy(l:first_problems[a:type])
    endif

    return {}
endfunction