@@ -49,6 +49,11 @@ type PublishDiagnosticRecord struct {
4949 Message string `json:"message"`
5050}
5151
52+ type DiagnosticsUpdate struct {
53+ FilePath string
54+ Diagnostics []Diagnostic
55+ }
56+
5257type Filter struct {
5358 FilePath string
5459 Severity string
@@ -95,22 +100,49 @@ func LoadSnapshot(path string) ([]Diagnostic, error) {
95100 return NormalizeDiagnostics (diagnostics ), nil
96101}
97102
103+ func ApplyPublishDiagnosticsSnapshot (path string , data []byte ) ([]Diagnostic , error ) {
104+ if path == "" {
105+ return nil , os .ErrInvalid
106+ }
107+ update , err := DiagnosticsUpdateFromPublishDiagnostics (data )
108+ if err != nil {
109+ return nil , err
110+ }
111+ existing , err := LoadSnapshot (path )
112+ if err != nil {
113+ return nil , err
114+ }
115+ updated := ApplyDiagnosticsForFile (existing , update .FilePath , update .Diagnostics )
116+ if err := WriteSnapshot (path , updated ); err != nil {
117+ return nil , err
118+ }
119+ return updated , nil
120+ }
121+
98122func DiagnosticsFromPublishDiagnostics (data []byte ) ([]Diagnostic , error ) {
123+ update , err := DiagnosticsUpdateFromPublishDiagnostics (data )
124+ if err != nil {
125+ return nil , err
126+ }
127+ return update .Diagnostics , nil
128+ }
129+
130+ func DiagnosticsUpdateFromPublishDiagnostics (data []byte ) (DiagnosticsUpdate , error ) {
99131 var params PublishDiagnosticsParams
100132 if err := json .Unmarshal (data , & params ); err != nil {
101- return nil , err
133+ return DiagnosticsUpdate {} , err
102134 }
103135 if strings .TrimSpace (params .URI ) == "" {
104136 var wrapper struct {
105137 Params PublishDiagnosticsParams `json:"params"`
106138 }
107139 if err := json .Unmarshal (data , & wrapper ); err != nil {
108- return nil , err
140+ return DiagnosticsUpdate {} , err
109141 }
110142 params = wrapper .Params
111143 }
112144 if strings .TrimSpace (params .URI ) == "" {
113- return nil , fmt .Errorf ("publishDiagnostics uri is required" )
145+ return DiagnosticsUpdate {} , fmt .Errorf ("publishDiagnostics uri is required" )
114146 }
115147 filePath := URIToPath (params .URI )
116148 out := make ([]Diagnostic , 0 , len (params .Diagnostics ))
@@ -124,7 +156,10 @@ func DiagnosticsFromPublishDiagnostics(data []byte) ([]Diagnostic, error) {
124156 Message : diagnostic .Message ,
125157 })
126158 }
127- return NormalizeDiagnostics (out ), nil
159+ return DiagnosticsUpdate {
160+ FilePath : normalizePath (filePath ),
161+ Diagnostics : NormalizeDiagnostics (out ),
162+ }, nil
128163}
129164
130165func ApplyDiagnosticsUpdate (existing []Diagnostic , update []Diagnostic ) []Diagnostic {
@@ -147,6 +182,25 @@ func ApplyDiagnosticsUpdate(existing []Diagnostic, update []Diagnostic) []Diagno
147182 return NormalizeDiagnostics (out )
148183}
149184
185+ func ApplyDiagnosticsForFile (existing []Diagnostic , filePath string , diagnostics []Diagnostic ) []Diagnostic {
186+ filePath = normalizePath (filePath )
187+ if filePath == "" {
188+ return NormalizeDiagnostics (existing )
189+ }
190+ out := make ([]Diagnostic , 0 , len (existing )+ len (diagnostics ))
191+ for _ , diagnostic := range NormalizeDiagnostics (existing ) {
192+ if diagnostic .FilePath == filePath {
193+ continue
194+ }
195+ out = append (out , diagnostic )
196+ }
197+ for _ , diagnostic := range diagnostics {
198+ diagnostic .FilePath = filePath
199+ out = append (out , diagnostic )
200+ }
201+ return NormalizeDiagnostics (out )
202+ }
203+
150204func URIToPath (raw string ) string {
151205 raw = strings .TrimSpace (raw )
152206 parsed , err := url .Parse (raw )
0 commit comments