| 209 | } |
| 210 | |
| 211 | func (fs *overlayFS) processChanges(changes []FileChange) (FileChangeSummary, map[tspath.Path]*Overlay) { |
| 212 | fs.mu.Lock() |
| 213 | defer fs.mu.Unlock() |
| 214 | |
| 215 | var result FileChangeSummary |
| 216 | newOverlays := maps.Clone(fs.overlays) |
| 217 | |
| 218 | // Reduced collection of changes that occurred on a single file |
| 219 | type fileEvents struct { |
| 220 | openChange *FileChange |
| 221 | closeChange *FileChange |
| 222 | watchChanged bool |
| 223 | changes []*FileChange |
| 224 | saved bool |
| 225 | created bool |
| 226 | deleted bool |
| 227 | } |
| 228 | |
| 229 | fileEventMap := make(map[lsproto.DocumentUri]*fileEvents) |
| 230 | |
| 231 | for _, change := range changes { |
| 232 | uri := change.URI |
| 233 | events, exists := fileEventMap[uri] |
| 234 | if exists { |
| 235 | if events.openChange != nil { |
| 236 | panic("should see no changes after open") |
| 237 | } |
| 238 | } else { |
| 239 | events = &fileEvents{} |
| 240 | fileEventMap[uri] = events |
| 241 | } |
| 242 | |
| 243 | if !result.IncludesWatchChangeOutsideNodeModules && change.Kind.IsWatchKind() && !strings.Contains(string(uri), "/node_modules/") { |
| 244 | result.IncludesWatchChangeOutsideNodeModules = true |
| 245 | } |
| 246 | |
| 247 | switch change.Kind { |
| 248 | case FileChangeKindOpen: |
| 249 | if events.closeChange != nil { |
| 250 | events.closeChange = nil |
| 251 | } |
| 252 | events.openChange = &change |
| 253 | events.watchChanged = false |
| 254 | events.changes = nil |
| 255 | events.saved = false |
| 256 | events.created = false |
| 257 | events.deleted = false |
| 258 | case FileChangeKindClose: |
| 259 | events.closeChange = &change |
| 260 | events.changes = nil |
| 261 | events.saved = false |
| 262 | events.watchChanged = false |
| 263 | case FileChangeKindChange: |
| 264 | if events.closeChange != nil { |
| 265 | panic("should see no changes after close") |
| 266 | } |
| 267 | events.changes = append(events.changes, &change) |
| 268 | events.saved = false |