anchor.diff:                      Async.StartInThreadPoolSafe(worker (fastData.SymbolUses, project, snapshot), cancelToken.Token)
           | _ -> ()
   
  +    let updateSyntaxConstructClassifiers force =
  +        let cancelToken = newCancellationToken fastStageCancellationToken
  +        let snapshot = getCurrentSnapshot()
  +        let needUpdate =
  +            match snapshot, force, fastState.Value with
  +            | None, _, _ -> false
  +            | _, true, _ -> true
  +            | _, _, FastStage.NoData -> true
  +            | Some snapshot, _, FastStage.Updating oldSnapshot -> oldSnapshot <> snapshot
  +            | Some snapshot, _, FastStage.Data { Snapshot = oldSnapshot } -> oldSnapshot <> snapshot
  +
  +        snapshot |> Option.iter (fun snapshot -> 
  +            fastState.Swap (fun _ -> Updating snapshot) |> ignore)
  +                
  +        if needUpdate then
  +            let worker = async {
  +                match getCurrentProject(), getCurrentSnapshot() with
  +                | Some currentProject, Some snapshot ->
  +                    debug "[SyntaxConstructClassifier] - Effective update"
  +                    let pf = Profiler()
  +                                        
  +                    let! parseResults = pf.TimeAsync "ParseFileInProject" <| fun _ ->
  +                        vsLanguageService.ParseFileInProject(textDocument.FilePath, snapshot.GetText(), currentProject)
  +
  +                    let lexer = vsLanguageService.CreateLexer(snapshot, currentProject.CompilerOptions)
  +
  +                    let! allSymbolsUses = pf.TimeAsync "GetAllUsesOfAllSymbolsInFile" <| fun _ ->
  +                        vsLanguageService.GetAllUsesOfAllSymbolsInFile(
  +                            snapshot, textDocument.FilePath, currentProject, AllowStaleResults.No, false, pf)
  +
  +                    let getTextLineOneBased i = snapshot.GetLineFromLineNumber(i).GetText()
  +
  +                    let spans = pf.Time "getCategoriesAndLocations" <| fun _ ->
  +                        getCategoriesAndLocations (allSymbolsUses, parseResults.ParseTree, lexer, getTextLineOneBased, [], None)
  +                        |> Array.sortBy (fun { WordSpan = { Line = line }} -> line)
  +
  +                    let spans = 
  +                        match slowState.Value with
  +                        | SlowStage.Data { UnusedSpans = oldUnusedSpans } ->
  +                            spans
  +                            |> Array.filter (fun s ->
  +                                not (oldUnusedSpans |> Map.containsKey s.WordSpan))
  +                            |> Array.append (oldUnusedSpans |> Map.toArray |> Array.map snd)
  +                        | _ -> spans
  +
  +                    let spans = spans |> Array.sortBy (fun { WordSpan = { Line = line }} -> line)
  +                    
  +                    let! singleSymbolsProjects = async {
  +                        if includeUnusedReferences() then
  +                            let getSymbolDeclLocation fsSymbol = projectFactory.GetSymbolDeclarationLocation fsSymbol textDocument.FilePath currentProject
  +                            let singleDefs = UnusedDeclarations.getSingleDeclarations allSymbolsUses
  +                            return!
  +                                singleDefs
  +                                |> Async.Array.map (fun symbol ->
  +                                    vsLanguageService.GetSymbolDeclProjects getSymbolDeclLocation currentProject symbol)
  +                                |> Async.map (
  +                                       Array.choose id 
  +                                    >> Array.concat 
  +                                    >> Seq.distinct 
  +                                    >> Seq.map (fun opts -> 
  +                                        { Options = opts
  +                                          // we mark standalone FSX's fake project as already checked 
  +                                          // because otherwise the slow stage never completes
  +                                          Checked = currentProject.IsForStandaloneScript })
  +                                    >> Seq.toList)
  +                        else return [] }
  +                    
  +                    fastState.Swap (fun _ -> 
  +                        FastStage.Data 
  +                            { Snapshot = snapshot
  +                              Spans = spans
  +                              SymbolUses = allSymbolsUses
  +                              SingleSymbolsProjects = singleSymbolsProjects }) |> ignore  
  +
  +                    triggerClassificationChanged "UpdateSyntaxConstructClassifiers"
  +
  +                    if isSlowStageEnabled() then
  +                        if currentProject.IsForStandaloneScript then
  +                            updateUnusedDeclarations()
  +                        else
  +                            let! currentProjectOpts = vsLanguageService.GetProjectCheckerOptions currentProject
  +                            vsLanguageService.StartBackgroundCompile currentProjectOpts
  +
  +                    pf.Stop()
  +                    Logging.logInfo "[SyntaxConstructClassifier] [Fast stage] %s" pf.Result
  +                    
  +                | _ -> () } 
  +            Async.StartInThreadPoolSafe (worker, cancelToken.Token) 
  +
       let dte = serviceProvider.GetService<EnvDTE.DTE, SDTE>()
       let events: EnvDTE80.Events2 option = tryCast dte.Events
       let onBuildDoneHandler = EnvDTE._dispBuildEvents_OnBuildProjConfigDoneEventHandler (fun project _ _ _ _ ->
  
positive.code:                 let! symbolsUses = vsLanguageService.GetUnusedDeclarations(symbolsUses, project, getSymbolDeclLocation, pf) |> liftAsync
                  let lexer = vsLanguageService.CreateLexer(snapshot, project.CompilerOptions)     
                  let getTextLineOneBased i = snapshot.GetLineFromLineNumber(i).GetText()
                  let! parseResults = pf.Time "parseFileInProject" <| fun _ ->
                      vsLanguageService.ParseFileInProject(textDocument.FilePath, snapshot.GetText(), project) |> liftAsync
                  
                  let includeUnusedOpens = 
                      includeUnusedOpens 
                      && not (isSignatureExtension(Path.GetExtension(textDocument.FilePath)) 
                      && project.IsForStandaloneScript)
  
                  let! entities, openDecls = 
                      if includeUnusedOpens then
                          getOpenDeclarations (snapshot.GetText()) project parseResults.ParseTree getTextLineOneBased pf 
                      else async { return None, [] }
                      |> liftAsync
  
negative.code:                 spans
                  // Locations are sorted, so we can safely filter them efficiently
                  |> Seq.skipWhile (fun { WordSpan = { Line = line }} -> line < spanStartLine)
                  |> Seq.choose (fun columnSpan -> 
                      maybe {
                          let! clType = getClassificationType columnSpan.Category
                          // Create a span on the original snapshot
                          let! span = fromRange snapshot (columnSpan.WordSpan.ToRange())
                          // Translate the span to the new snapshot
                          return clType, span.TranslateTo(newSnapshotSpan.Snapshot, SpanTrackingMode.EdgeExclusive) 
                      })
  