| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package cache |
| |
| import ( |
| "strings" |
| |
| "golang.org/x/tools/gopls/internal/lsp/source" |
| "golang.org/x/tools/gopls/internal/span" |
| "golang.org/x/tools/internal/persistent" |
| ) |
| |
| // TODO(euroelessar): Use generics once support for go1.17 is dropped. |
| |
| type filesMap struct { |
| impl *persistent.Map |
| } |
| |
| // uriLessInterface is the < relation for "any" values containing span.URIs. |
| func uriLessInterface(a, b interface{}) bool { |
| return a.(span.URI) < b.(span.URI) |
| } |
| |
| func newFilesMap() filesMap { |
| return filesMap{ |
| impl: persistent.NewMap(uriLessInterface), |
| } |
| } |
| |
| func (m filesMap) Clone() filesMap { |
| return filesMap{ |
| impl: m.impl.Clone(), |
| } |
| } |
| |
| func (m filesMap) Destroy() { |
| m.impl.Destroy() |
| } |
| |
| func (m filesMap) Get(key span.URI) (source.FileHandle, bool) { |
| value, ok := m.impl.Get(key) |
| if !ok { |
| return nil, false |
| } |
| return value.(source.FileHandle), true |
| } |
| |
| func (m filesMap) Range(do func(key span.URI, value source.FileHandle)) { |
| m.impl.Range(func(key, value interface{}) { |
| do(key.(span.URI), value.(source.FileHandle)) |
| }) |
| } |
| |
| func (m filesMap) Set(key span.URI, value source.FileHandle) { |
| m.impl.Set(key, value, nil) |
| } |
| |
| func (m filesMap) Delete(key span.URI) { |
| m.impl.Delete(key) |
| } |
| |
| func parseKeyLessInterface(a, b interface{}) bool { |
| return parseKeyLess(a.(parseKey), b.(parseKey)) |
| } |
| |
| func parseKeyLess(a, b parseKey) bool { |
| if a.mode != b.mode { |
| return a.mode < b.mode |
| } |
| if a.file.Hash != b.file.Hash { |
| return a.file.Hash.Less(b.file.Hash) |
| } |
| return a.file.URI < b.file.URI |
| } |
| |
| type isActivePackageCacheMap struct { |
| impl *persistent.Map |
| } |
| |
| func newIsActivePackageCacheMap() isActivePackageCacheMap { |
| return isActivePackageCacheMap{ |
| impl: persistent.NewMap(func(a, b interface{}) bool { |
| return a.(PackageID) < b.(PackageID) |
| }), |
| } |
| } |
| |
| func (m isActivePackageCacheMap) Clone() isActivePackageCacheMap { |
| return isActivePackageCacheMap{ |
| impl: m.impl.Clone(), |
| } |
| } |
| |
| func (m isActivePackageCacheMap) Destroy() { |
| m.impl.Destroy() |
| } |
| |
| func (m isActivePackageCacheMap) Get(key PackageID) (bool, bool) { |
| value, ok := m.impl.Get(key) |
| if !ok { |
| return false, false |
| } |
| return value.(bool), true |
| } |
| |
| func (m isActivePackageCacheMap) Set(key PackageID, value bool) { |
| m.impl.Set(key, value, nil) |
| } |
| |
| type parseKeysByURIMap struct { |
| impl *persistent.Map |
| } |
| |
| func newParseKeysByURIMap() parseKeysByURIMap { |
| return parseKeysByURIMap{ |
| impl: persistent.NewMap(uriLessInterface), |
| } |
| } |
| |
| func (m parseKeysByURIMap) Clone() parseKeysByURIMap { |
| return parseKeysByURIMap{ |
| impl: m.impl.Clone(), |
| } |
| } |
| |
| func (m parseKeysByURIMap) Destroy() { |
| m.impl.Destroy() |
| } |
| |
| func (m parseKeysByURIMap) Get(key span.URI) ([]parseKey, bool) { |
| value, ok := m.impl.Get(key) |
| if !ok { |
| return nil, false |
| } |
| return value.([]parseKey), true |
| } |
| |
| func (m parseKeysByURIMap) Range(do func(key span.URI, value []parseKey)) { |
| m.impl.Range(func(key, value interface{}) { |
| do(key.(span.URI), value.([]parseKey)) |
| }) |
| } |
| |
| func (m parseKeysByURIMap) Set(key span.URI, value []parseKey) { |
| m.impl.Set(key, value, nil) |
| } |
| |
| func (m parseKeysByURIMap) Delete(key span.URI) { |
| m.impl.Delete(key) |
| } |
| |
| func packageKeyLessInterface(x, y interface{}) bool { |
| return packageKeyLess(x.(packageKey), y.(packageKey)) |
| } |
| |
| func packageKeyLess(x, y packageKey) bool { |
| if x.mode != y.mode { |
| return x.mode < y.mode |
| } |
| return x.id < y.id |
| } |
| |
| type knownDirsSet struct { |
| impl *persistent.Map |
| } |
| |
| func newKnownDirsSet() knownDirsSet { |
| return knownDirsSet{ |
| impl: persistent.NewMap(func(a, b interface{}) bool { |
| return a.(span.URI) < b.(span.URI) |
| }), |
| } |
| } |
| |
| func (s knownDirsSet) Clone() knownDirsSet { |
| return knownDirsSet{ |
| impl: s.impl.Clone(), |
| } |
| } |
| |
| func (s knownDirsSet) Destroy() { |
| s.impl.Destroy() |
| } |
| |
| func (s knownDirsSet) Contains(key span.URI) bool { |
| _, ok := s.impl.Get(key) |
| return ok |
| } |
| |
| func (s knownDirsSet) Range(do func(key span.URI)) { |
| s.impl.Range(func(key, value interface{}) { |
| do(key.(span.URI)) |
| }) |
| } |
| |
| func (s knownDirsSet) SetAll(other knownDirsSet) { |
| s.impl.SetAll(other.impl) |
| } |
| |
| func (s knownDirsSet) Insert(key span.URI) { |
| s.impl.Set(key, nil, nil) |
| } |
| |
| func (s knownDirsSet) Remove(key span.URI) { |
| s.impl.Delete(key) |
| } |
| |
| // analysisKeyLessInterface is the less-than relation for analysisKey |
| // values wrapped in an interface. |
| func analysisKeyLessInterface(a, b interface{}) bool { |
| x, y := a.(analysisKey), b.(analysisKey) |
| if cmp := strings.Compare(x.analyzerNames, y.analyzerNames); cmp != 0 { |
| return cmp < 0 |
| } |
| return x.pkgid < y.pkgid |
| } |