Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1374 from vasily-kirichenko/unused-declarations-fix
Browse files Browse the repository at this point in the history
fixed: UnusedDeclarations.getSingleDeclarations returns actually used…
  • Loading branch information
dungpa committed Apr 25, 2016
2 parents 513d1e9 + 5388108 commit 30b95a0
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/FSharpVSPowerTools.Core/LanguageService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ type WordSpan =
Line = r.StartLine
StartCol = r.StartColumn
EndCol = r.EndColumn }
member x.ToRange() = x.Line, x.StartCol, x.Line, x.EndCol
member x.Range = lazy (x.Line, x.StartCol, x.Line, x.EndCol)

[<AbstractClass>]
type LexerBase() =
Expand Down
32 changes: 18 additions & 14 deletions src/FSharpVSPowerTools.Core/TypedAstUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -299,28 +299,32 @@ module TypedAstPatterns =
module UnusedDeclarations =
open System.Collections.Generic

let symbolsComparer =
{ new IEqualityComparer<FSharpSymbol> with
member __.Equals (x, y) = x.IsEffectivelySameAs y
member __.GetHashCode x = x.GetHashCode() }
let symbolUseComparer =
{ new IEqualityComparer<FSharpSymbolUse> with
member __.Equals (x, y) = x.Symbol.IsEffectivelySameAs y.Symbol
member __.GetHashCode x = x.Symbol.GetHashCode() }

let getSingleDeclarations (symbolsUses: SymbolUse[]): FSharpSymbol[] =
symbolsUses
|> Seq.groupBy (fun x -> x.SymbolUse.Symbol)
|> Seq.choose (fun (symbol, uses) ->
match symbol with
| UnionCase _ when isSymbolLocalForProject symbol -> Some symbol
let symbols = Dictionary<FSharpSymbolUse, int>(symbolUseComparer)

for symbolUse in symbolsUses do
match symbols.TryGetValue symbolUse.SymbolUse with
| true, count -> symbols.[symbolUse.SymbolUse] <- count + 1
| _ -> symbols.[symbolUse.SymbolUse] <- 1

symbols
|> Seq.choose (fun (KeyValue(symbolUse, count)) ->
match symbolUse.Symbol with
| UnionCase _ when isSymbolLocalForProject symbolUse.Symbol -> Some symbolUse.Symbol
// Determining that a record, DU or module is used anywhere requires
// inspecting all their enclosed entities (fields, cases and func / vals)
// for usefulness, which is too expensive to do. Hence we never gray them out.
| Entity ((Record | UnionType | Interface | FSharpModule), _, _ | Class) -> None
// FCS returns inconsistent results for override members; we're going to skip these symbols.
// FCS returns inconsistent results for override members; we're skipping these symbols.
| MemberFunctionOrValue func when func.IsOverrideOrExplicitInterfaceImplementation -> None
// Usage of DU case parameters does not give any meaningful feedback; we never gray them out.
| Parameter -> None
| _ ->
match List.ofSeq uses with
| [symbolUse] when symbolUse.SymbolUse.IsFromDefinition && isSymbolLocalForProject symbol ->
Some symbol
| _ when count = 1 && symbolUse.IsFromDefinition && isSymbolLocalForProject symbolUse.Symbol ->
Some symbolUse.Symbol
| _ -> None)
|> Seq.toArray
2 changes: 1 addition & 1 deletion src/FSharpVSPowerTools.Logic/ClassifierTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type internal CategorizedSnapshotSpan (columnSpan: CategorizedColumnSpan<ITextSn
snapshotSpan.Swap (fun oldSpan ->
oldSpan
|> Option.orTry (fun _ ->
fromRange originalSnapshot (columnSpan.WordSpan.ToRange())
fromRange originalSnapshot columnSpan.WordSpan.Range.Value
|> Option.map (fun span ->
{ Span = span
Line = span.Start.GetContainingLine().LineNumber }))
Expand Down
26 changes: 13 additions & 13 deletions src/FSharpVSPowerTools.Logic/UnusedSymbolClassifier.fs
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,17 @@ type UnusedSymbolClassifier

let! openDeclarations = OpenDeclarationGetter.getOpenDeclarations ast entities qualifyOpenDeclarations
return
(entities
|> Option.map (fun entities ->
entities
|> Seq.groupBy (fun e -> e.FullName)
|> Seq.map (fun (fullName, entities) ->
fullName,
entities
|> Seq.map (fun e -> e.CleanedIdents)
|> Seq.toList)
|> Dict.ofSeq),
openDeclarations)
entities
|> Option.map (fun entities ->
entities
|> Seq.groupBy (fun e -> e.FullName)
|> Seq.map (fun (fullName, entities) ->
fullName,
entities
|> Seq.map (fun e -> e.CleanedIdents)
|> Seq.toList)
|> Dict.ofSeq),
openDeclarations
}

let checkAstIsNotEmpty (ast: ParsedInput) =
Expand Down Expand Up @@ -265,7 +265,7 @@ type UnusedSymbolClassifier

match projects |> List.tryFind (fun p -> not p.Checked) with
| Some { Options = opts } ->
// there is at least one yet unchecked project, start compilation on it
// there is at least one yet unchecked project, start compiling it
vsLanguageService.CheckProjectInBackground opts
| None ->
// all the needed projects have been checked in background, let's calculate unused symbols
Expand Down Expand Up @@ -300,7 +300,7 @@ type UnusedSymbolClassifier
|> Option.map (fun data ->
data.Spans.Spans
|> Array.choose (fun wordSpan ->
fromRange data.Snapshot (wordSpan.ColumnSpan.WordSpan.ToRange())
fromRange data.Snapshot wordSpan.ColumnSpan.WordSpan.Range.Value
|> Option.map (fun span -> TagSpan(span, UnusedDeclarationTag()) :> ITagSpan<_>)))
|> Option.getOrElse [||]

Expand Down

0 comments on commit 30b95a0

Please sign in to comment.