@@ -477,6 +477,20 @@ type FSharpSymbolUse(g:TcGlobals, denv: DisplayEnv, symbol:FSharpSymbol, itemOcc
477477member __.Range = Range.toZ range
478478member __.RangeAlternate = range
479479
480+ [<RequireQualifiedAccess>]
481+ type SemanticClassificationType =
482+ | ReferenceType
483+ | ValueType
484+ | UnionCase
485+ | Function
486+ | Property
487+ | MutableVar
488+ | Module
489+ | Printf
490+ | ComputationExpression
491+ | IntrinsicType
492+ | Enumeration
493+
480494// A scope represents everything we get back from the typecheck of a file.
481495// It acts like an in-memory database about the file.
482496// It is effectively immutable and not updated: when we re-typecheck we just drop the previous
@@ -1399,7 +1413,7 @@ type TypeCheckInfo
13991413 sSymbolUses.GetFormatSpecifierLocations()
14001414
14011415// Not, this does not have to be a SyncOp, it can be called from any thread
1402- member scope.GetExtraColorizations () =
1416+ member scope.GetSemanticClassification () : ( range * SemanticClassificationType ) [] =
14031417let (| LegitTypeOccurence | _ |) = function
14041418| ItemOccurence.UseInType
14051419| ItemOccurence.UseInAttribute
@@ -1418,25 +1432,51 @@ type TypeCheckInfo
14181432match cnrwith
14191433// 'seq' in 'seq { ... }' gets colored as keywords
14201434| CNR(_, ( Item.Value vref), ItemOccurence.Use, _, _, _, m) when valRefEq g g.seq_ vref vref->
1421- Some( m, FSharpTokenColorKind.Keyword)
1435+ Some( m, SemanticClassificationType.ComputationExpression)
1436+
1437+ | CNR(_, ( Item.Value vref), _, _, _, _, m) when isFunction g vref.Type->
1438+ if vref.IsPropertyGetterMethod|| vref.IsPropertySetterMethodthen
1439+ Some( m, SemanticClassificationType.Property)
1440+ elif not ( IsOperatorName vref.DisplayName) then
1441+ Some( m, SemanticClassificationType.Function)
1442+ else None
1443+ | CNR(_, ( Item.Value vref), _, _, _, _, m) when vref.IsMutable->
1444+ Some( m, SemanticClassificationType.MutableVar)
1445+ // todo here we should check if a `vref` is of type `ref`1`
1446+ // (the commented code does not work)
1447+
1448+ //| CNR(_, (Item.Value vref), _, _, _, _, m) ->
1449+ // match vref.TauType with
1450+ // | TType.TType_app(tref, _) -> // g.refcell_tcr_canon.t _refcell_tcr_canon canon.Deref.type vref ->
1451+ // if g.refcell_tcr_canon.Deref.Stamp = tref.Deref.Stamp then
1452+ // Some (m, SemanticClassificationType.MutableVar)
1453+ // else None
1454+ // | _ -> None
1455+ | CNR(_, Item.RecdField rfinfo, _, _, _, _, m) when rfinfo.RecdField.IsMutable&& rfinfo.LiteralValue.IsNone->
1456+ Some( m, SemanticClassificationType.MutableVar)
1457+ | CNR(_, Item.MethodGroup(_, _, _), _, _, _, _, m) ->
1458+ Some( m, SemanticClassificationType.Function)
14221459// custom builders, custom operations get colored as keywords
14231460| CNR(_, ( Item.CustomBuilder_ | Item.CustomOperation_), ItemOccurence.Use, _, _, _, m) ->
1424- Some( m, FSharpTokenColorKind.Keyword )
1461+ Some( m, SemanticClassificationType.ComputationExpression )
14251462// well known type aliases get colored as keywords
14261463| CNR(_, ( Item.Types( n, _)), _, _, _, _, m) when keywordTypes.Contains( n) ->
1427- Some( m, FSharpTokenColorKind.Keyword )
1464+ Some( m, SemanticClassificationType.IntrinsicType )
14281465// types get colored as types when they occur in syntactic types or custom attributes
14291466// typevariables get colored as types when they occur in syntactic types custom builders, custom operations get colored as keywords
14301467| CNR(_, Item.Types(_, [ OptionalArgumentAttribute]), LegitTypeOccurence, _, _, _, _) -> None
14311468| CNR(_, Item.CtorGroup(_, [ MethInfo.FSMeth(_, OptionalArgumentAttribute, _, _)]), LegitTypeOccurence, _, _, _, _) -> None
14321469| CNR(_, Item.Types_, LegitTypeOccurence, _, _, _, m) ->
1433- Some( m, FSharpTokenColorKind.TypeName )
1470+ Some( m, SemanticClassificationType.ReferenceType )
14341471| CNR(_, ( Item.TypeVar_ | Item.UnqualifiedType_ | Item.CtorGroup_), LegitTypeOccurence, _, _, _, m) ->
1435- Some( m, FSharpTokenColorKind.TypeName )
1472+ Some( m, SemanticClassificationType.ReferenceType )
14361473| CNR(_, Item.ModuleOrNamespaces refs, LegitTypeOccurence, _, _, _, m) when refs|> List.exists( fun x -> x.IsModule) ->
1437- Some( m, FSharpTokenColorKind.TypeName)
1474+ Some( m, SemanticClassificationType.ReferenceType)
1475+ | CNR(_, ( Item.ActivePatternCase_ | Item.UnionCase_ | Item.ActivePatternResult_), _, _, _, _, m) ->
1476+ Some( m, SemanticClassificationType.UnionCase)
14381477| _ -> None)
14391478|> Seq.toArray
1479+ |> Array.append( sSymbolUses.GetFormatSpecifierLocations() |> Array.map( fun m -> m, SemanticClassificationType.Printf))
14401480
14411481member x.ScopeResolutions = sResolutions
14421482member x.ScopeSymbolUses = sSymbolUses
@@ -2029,12 +2069,12 @@ type FSharpCheckFileResults(errors: FSharpErrorInfo[], scopeOptX: TypeCheckInfo
20292069// This operation is not asynchronous - GetFormatSpecifierLocations can be run on the calling thread
20302070 scope.GetFormatSpecifierLocations())
20312071
2032- member info.GetExtraColorizationsAlternate () =
2072+ member info.GetSemanticClassification () =
20332073 threadSafeOp
20342074( fun () -> [| |])
20352075( fun ( scope , _builder , _reactor ) ->
20362076// This operation is not asynchronous - GetExtraColorizations can be run on the calling thread
2037- scope.GetExtraColorizations ())
2077+ scope.GetSemanticClassification ())
20382078
20392079member info.PartialAssemblySignature =
20402080 threadSafeOp
@@ -2202,7 +2242,7 @@ type BackgroundCompiler(referenceResolver, projectCacheSize, keepAssemblyContent
22022242 requiredToKeep=( fun ( builderOpt , _ , _ ) -> match builderOptwith None-> false | Some b-> b.IsBeingKeptAliveApartFromCacheEntry),
22032243 onDiscard= ( fun ( _ , _ , decrement ) -> decrement.Dispose()))
22042244
2205- let getOrCreateBuilder ( options , ct ) =
2245+ let getOrCreateBuilder ( options , ct ) =
22062246match incrementalBuildersCache.TryGet optionswith
22072247| Some b-> b
22082248| None->
@@ -2482,7 +2522,7 @@ type BackgroundCompiler(referenceResolver, projectCacheSize, keepAssemblyContent
24822522let execWithReactorAsync action = reactor.EnqueueAndAwaitOpAsync( " ParseAndCheckFileInProject" + filename, action)
24832523async {
24842524let! ct = Async.CancellationToken
2485- let builderOpt , creationErrors , _ = getOrCreateBuilder( options, ct) // Q: Whis it it ok to ignore creationErrors in the build cache? A: These errors will be appended into the typecheck results
2525+ let! builderOpt , creationErrors , _ = execWithReactorAsync <| fun _ -> getOrCreateBuilder( options, ct) // Q: Whis it it ok to ignore creationErrors in the build cache? A: These errors will be appended into the typecheck results
24862526use _unwind= IncrementalBuilder.KeepBuilderAlive builderOpt
24872527match builderOptwith
24882528| None->