Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf6d4a7d

Browse files
fix cache locking
1 parent0982b92 commitf6d4a7d

File tree

1 file changed

+67
-67
lines changed

1 file changed

+67
-67
lines changed

‎vsintegration/src/FSharp.Editor/Diagnostics/SimplifyNameDiagnosticAnalyzer.fs‎

Lines changed: 67 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type internal SimplifyNameDiagnosticAnalyzer() =
2727
letgetChecker(document:Document)= document.Project.Solution.Workspace.Services.GetService<FSharpCheckerWorkspaceService>().Checker
2828
letgetPlidLength(plid:string list)=(plid|> List.sumBy String.length)+ plid.Length
2929
static letcache= ConditionalWeakTable<DocumentId, TextVersionHash* ImmutableArray<Diagnostic>>()
30+
static letguard=new SemaphoreSlim(1)
3031

3132
static letDescriptor=
3233
DiagnosticDescriptor(
@@ -50,73 +51,72 @@ type internal SimplifyNameDiagnosticAnalyzer() =
5051
| Some options->
5152
let!textVersion= document.GetTextVersionAsync(cancellationToken)
5253
lettextVersionHash= textVersion.GetHashCode()
53-
54-
return! lock cache(fun _->
55-
asyncMaybe{
56-
match cache.TryGetValue document.Idwith
57-
|true,(oldTextVersionHash, diagnostics)when oldTextVersionHash= textVersionHash->return diagnostics
58-
|_->
59-
let!sourceText= document.GetTextAsync()
60-
letchecker= getChecker document
61-
let!_,checkResults= checker.ParseAndCheckDocument(document, options, sourceText)
62-
let!symbolUses= checkResults.GetAllUsesOfAllSymbolsInFile()|> liftAsync
63-
let mutableresult= ResizeArray()
64-
letsymbolUses=
65-
symbolUses
66-
|> Array.Parallel.map(fun symbolUse->
67-
letlineStr= sourceText.Lines.[Line.toZ symbolUse.RangeAlternate.StartLine].ToString()
68-
// for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now")
69-
letplid,name= QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn-1)
70-
// `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`,
71-
// so we have to calculate plid's start ourselves.
72-
letplidStartCol= symbolUse.RangeAlternate.EndColumn- name.Length-(getPlidLength plid)
73-
symbolUse, plid, plidStartCol, name)
74-
|> Array.filter(fun(_,plid,_,_)->not(List.isEmpty plid))
75-
|> Array.groupBy(fun(symbolUse,_,plidStartCol,_)-> symbolUse.RangeAlternate.StartLine, plidStartCol)
76-
|> Array.map(fun(_,xs)-> xs|> Array.maxBy(fun(symbolUse,_,_,_)-> symbolUse.RangeAlternate.EndColumn))
77-
78-
for symbolUse, plid, plidStartCol, namein symbolUsesdo
79-
ifnot symbolUse.IsFromDefinitionthen
80-
letposAtStartOfName=
81-
letr= symbolUse.RangeAlternate
82-
if r.StartLine= r.EndLinethen Range.mkPos r.StartLine(r.EndColumn- name.Length)
83-
else r.Start
84-
85-
letgetNecessaryPlid(plid:string list):Async<stringlist>=
86-
let recloop(rest:string list)(current:string list)=
87-
async{
88-
match restwith
89-
|[]->return current
90-
| headIdent:: restPlid->
91-
let!res= checkResults.IsRelativeNameResolvable(posAtStartOfName, current, symbolUse.Symbol.Item)
92-
if resthenreturn current
93-
elsereturn! loop restPlid(headIdent:: current)
94-
}
95-
loop(List.rev plid)[]
96-
97-
let!necessaryPlid= getNecessaryPlid plid|> liftAsync
98-
99-
match necessaryPlidwith
100-
| necessaryPlidwhen necessaryPlid= plid->()
101-
| necessaryPlid->
102-
letr= symbolUse.RangeAlternate
103-
letnecessaryPlidStartCol= r.EndColumn- name.Length-(getPlidLength necessaryPlid)
104-
105-
letunnecessaryRange=
106-
Range.mkRange r.FileName(Range.mkPos r.StartLine plidStartCol)(Range.mkPos r.EndLine necessaryPlidStartCol)
107-
108-
letrelativeName=(String.concat"." plid)+"."+ name
109-
result.Add(
110-
Diagnostic.Create(
111-
Descriptor,
112-
CommonRoslynHelpers.RangeToLocation(unnecessaryRange, sourceText, document.FilePath),
113-
properties=(dict[SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, relativeName]).ToImmutableDictionary()))
114-
115-
letdiagnostics= result.ToImmutableArray()
116-
cache.Remove(document.Id)|> ignore
117-
cache.Add(document.Id,(textVersionHash, diagnostics))
118-
return diagnostics
119-
})
54+
let!_= guard.WaitAsync(cancellationToken)|> Async.AwaitTask|> liftAsync
55+
try
56+
match cache.TryGetValue document.Idwith
57+
|true,(oldTextVersionHash, diagnostics)when oldTextVersionHash= textVersionHash->return diagnostics
58+
|_->
59+
let!sourceText= document.GetTextAsync()
60+
letchecker= getChecker document
61+
let!_,checkResults= checker.ParseAndCheckDocument(document, options, sourceText)
62+
let!symbolUses= checkResults.GetAllUsesOfAllSymbolsInFile()|> liftAsync
63+
let mutableresult= ResizeArray()
64+
letsymbolUses=
65+
symbolUses
66+
|> Array.Parallel.map(fun symbolUse->
67+
letlineStr= sourceText.Lines.[Line.toZ symbolUse.RangeAlternate.StartLine].ToString()
68+
// for `System.DateTime.Now` it returns ([|"System"; "DateTime"|], "Now")
69+
letplid,name= QuickParse.GetPartialLongNameEx(lineStr, symbolUse.RangeAlternate.EndColumn-1)
70+
// `symbolUse.RangeAlternate.Start` does not point to the start of plid, it points to start of `name`,
71+
// so we have to calculate plid's start ourselves.
72+
letplidStartCol= symbolUse.RangeAlternate.EndColumn- name.Length-(getPlidLength plid)
73+
symbolUse, plid, plidStartCol, name)
74+
|> Array.filter(fun(_,plid,_,_)->not(List.isEmpty plid))
75+
|> Array.groupBy(fun(symbolUse,_,plidStartCol,_)-> symbolUse.RangeAlternate.StartLine, plidStartCol)
76+
|> Array.map(fun(_,xs)-> xs|> Array.maxBy(fun(symbolUse,_,_,_)-> symbolUse.RangeAlternate.EndColumn))
77+
78+
for symbolUse, plid, plidStartCol, namein symbolUsesdo
79+
ifnot symbolUse.IsFromDefinitionthen
80+
letposAtStartOfName=
81+
letr= symbolUse.RangeAlternate
82+
if r.StartLine= r.EndLinethen Range.mkPos r.StartLine(r.EndColumn- name.Length)
83+
else r.Start
84+
85+
letgetNecessaryPlid(plid:string list):Async<stringlist>=
86+
let recloop(rest:string list)(current:string list)=
87+
async{
88+
match restwith
89+
|[]->return current
90+
| headIdent:: restPlid->
91+
let!res= checkResults.IsRelativeNameResolvable(posAtStartOfName, current, symbolUse.Symbol.Item)
92+
if resthenreturn current
93+
elsereturn! loop restPlid(headIdent:: current)
94+
}
95+
loop(List.rev plid)[]
96+
97+
let!necessaryPlid= getNecessaryPlid plid|> liftAsync
98+
99+
match necessaryPlidwith
100+
| necessaryPlidwhen necessaryPlid= plid->()
101+
| necessaryPlid->
102+
letr= symbolUse.RangeAlternate
103+
letnecessaryPlidStartCol= r.EndColumn- name.Length-(getPlidLength necessaryPlid)
104+
105+
letunnecessaryRange=
106+
Range.mkRange r.FileName(Range.mkPos r.StartLine plidStartCol)(Range.mkPos r.EndLine necessaryPlidStartCol)
107+
108+
letrelativeName=(String.concat"." plid)+"."+ name
109+
result.Add(
110+
Diagnostic.Create(
111+
Descriptor,
112+
CommonRoslynHelpers.RangeToLocation(unnecessaryRange, sourceText, document.FilePath),
113+
properties=(dict[SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, relativeName]).ToImmutableDictionary()))
114+
115+
letdiagnostics= result.ToImmutableArray()
116+
cache.Remove(document.Id)|> ignore
117+
cache.Add(document.Id,(textVersionHash, diagnostics))
118+
return diagnostics
119+
finally guard.Release()|> ignore
120120
| None->return ImmutableArray.Empty
121121
}
122122
|> Async.map(Option.defaultValue ImmutableArray.Empty)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp