anchor.diff:              | _ -> ()
           }
   
  -    let private parseModuleOrNamespace moduleOrNs =
  -        seq { let (SynModuleOrNamespace.SynModuleOrNamespace (_,_,_,decls,_,_,_,_)) = moduleOrNs
  -              yield! collectHashDirectives decls
  -              yield! collectOpens decls
  -              yield! Seq.collect parseDeclaration decls }
  +    let private parseModuleOrNamespace (SynModuleOrNamespace.SynModuleOrNamespace (longId,_,isModule,decls,_,attribs,_,r)) =
  +        seq {
  +            yield! parseAttributes attribs
  +            let idRange = longIdentRange longId
  +            let fullrange = Range.startToEnd idRange r  
  +            let collapse = Range.endToEnd idRange r 
  +            if isModule then
  +                yield! rcheck Scope.Module Collapse.Below fullrange collapse
  +
  +            yield! collectHashDirectives decls
  +            yield! collectOpens decls
  +            yield! Seq.collect parseDeclaration decls
  +        }
   
       type private LineNum = int
       type private LineStr = string
  -    type private CommentType = Regular | XmlDoc
  -    
  +    type private CommentType = SingleLine | XmlDoc
  +
       [<NoComparison>]
  -    type private CommentList = 
  +    type private CommentList =
           { Lines: ResizeArray<LineNum * LineStr>
             Type: CommentType }
  -        static member New ty lineStr = 
  +        static member New ty lineStr =
               { Type = ty; Lines = ResizeArray [| lineStr |] }
   
  -    let private (|Comment|_|) line =
  -        match line with
  -        | String.StartsWith "///" -> Some XmlDoc
  -        | String.StartsWith "//" -> Some Regular
  -        | _ -> None
  +    /// Determine if a line is a single line or xml docummentation comment
  +    let private (|Comment|_|) (line: string) =
  +        if line.StartsWith "///" then Some XmlDoc
  +        elif line.StartsWith "//" then Some SingleLine
  +        else None
   
       let getCommentRanges (lines: string[]) =
  -        let comments: CommentList list =
  -            lines
  -            |> Array.foldi (fun ((lastLineNum, currentComment: CommentList option, result) as state) lineNum lineStr ->
  +        let rec loop ((lastLineNum, currentComment: CommentList option, result) as state) (lines: string list) lineNum =
  +            match lines with
  +            | [] -> state
  +            | lineStr :: rest ->
                   match lineStr.TrimStart(), currentComment with
                   | Comment commentType, Some comment ->
  -                    if comment.Type = commentType && lineNum = lastLineNum + 1 then
  -                        comment.Lines.Add (lineNum, lineStr)
  -                        lineNum, currentComment, result
  -                    else lineNum, Some (CommentList.New commentType (lineNum, lineStr)), comment :: result
  -                | Comment commentType, None -> 
  -                    lineNum, Some (CommentList.New commentType (lineNum, lineStr)), result
  -                | _, Some comment -> 
  -                    lineNum, None, comment :: result
  -                | _ -> state) 
  -               (-1, None, [])
  -            |> fun (_, lastComment, comments) -> 
  -                match lastComment with 
  -                | Some comment -> 
  -                    comment :: comments 
  +                    loop(
  +                        if comment.Type = commentType && lineNum = lastLineNum + 1 then
  +                            comment.Lines.Add (lineNum, lineStr)
  +                            lineNum, currentComment, result
  +                        else lineNum, Some (CommentList.New commentType (lineNum, lineStr)), comment :: result) rest (lineNum + 1)
  +                | Comment commentType, None ->
  +                    loop(lineNum, Some (CommentList.New commentType (lineNum, lineStr)), result) rest (lineNum + 1)
  +                | _, Some comment ->
  +                    loop(lineNum, None, comment :: result) rest (lineNum + 1)
  +                | _ -> loop(lineNum, None, result) rest (lineNum + 1)
  +
  +        let comments: CommentList list =
  +            loop (-1, None, []) (List.ofArray lines) 0
  +            |> fun (_, lastComment, comments) ->
  +                match lastComment with
  +                | Some comment ->
  +                    comment :: comments
                   | _ -> comments
                   |> List.rev
   
  
positive.code:             let endCol = endStr.TrimEnd().Length
  
              let scopeType =
                  match comment.Type with 
                  | Regular -> Scope.Comment
                  | XmlDoc -> Scope.XmlDocComment
              ScopeRange(
                  scopeType, 
                  Collapse.Same, 
                  Range.mkRange 
                      "" 
                      (Range.mkPos (startLine + 1) startCol)
                      (Range.mkPos (endLine + 1) endCol)))
  
      let getOutliningRanges sourceLines tree =
          match tree with
          | ParsedInput.ImplFile implFile ->
              let (ParsedImplFileInput (_, _, _, _, _, modules, _)) = implFile
              let astBasedRanges = Seq.collect parseModuleOrNamespace modules
              let commentRanges = getCommentRanges sourceLines
              Seq.append astBasedRanges commentRanges
          | _ -> Seq.empty
  
  module Printf =
      [<NoComparison>]
  
negative.code:         )
  
  
  module Outlining =
      /// Set of visitor utilities, designed for the express purpose of fetching ranges
      /// from an untyped AST for the purposes of block structure.
      [<RequireQualifiedAccess>]
      module private Range =
  
          let unionOpts (r1:range option) (r2:range option) =
              match r1 , r2 with
              | None, None -> None
              | Some r, None -> Some r
              | None , Some r -> Some r
              | Some r1, Some r2 -> unionRanges r1 r2 |> Some
  
          /// Create a range starting at the end of r1 and finishing at the end of r2
          let inline endToEnd (r1: range) (r2: range) = mkFileIndexRange r1.FileIndex r1.End r2.End
  
          /// Create a range starting at the end of r1 and finishing at the start of r2
          let inline endToStart (r1: range) (r2: range) = mkFileIndexRange r1.FileIndex r1.End r2.Start
  
          /// Create a range beginning at the start of r1 and finishing at the end of r2
          let inline startToEnd (r1: range) (r2: range) = mkFileIndexRange r1.FileIndex r1.Start r2.End
  
          /// Create a range beginning at the start of r1 and finishing at the start of r2
          let inline startToStart (r1: range) (r2: range) = mkFileIndexRange r1.FileIndex r1.Start r2.Start
  
          /// Create a new range from r by shifting the starting column by m
          let inline modStart  (m:int) (r: range) =
              let modstart = mkPos r.StartLine (r.StartColumn+m)
              mkFileIndexRange r.FileIndex modstart r.End
  
          /// Create a new range from r by shifting the ending column by m
          let inline modEnd (m:int) (r: range) =
              let modend = mkPos r.EndLine (r.EndColumn+m)
              mkFileIndexRange r.FileIndex r.Start modend
  
  
          /// Produce a new range by adding modStart to the StartColumn of `r`
          /// and subtracting modEnd from the EndColumn of `r`
          let inline modBoth modStart modEnd (r:range) =
              let rStart = Range.mkPos r.StartLine (r.StartColumn+modStart)
              let rEnd   = Range.mkPos r.EndLine   (r.EndColumn - modEnd)
              mkFileIndexRange r.FileIndex rStart rEnd
  
      let longIdentRange (longId:LongIdent) =
          match longId with 
          | [] -> Range.range0
          | head::_ -> Range.startToEnd head.idRange (List.last longId).idRange
  
      /// Caclulate the range of the provided type arguments (<'a,...,'z>) 
      /// or return the range `other` when `typeArgs` = []
      let rangeOfTypeArgsElse other (typeArgs:SynTyparDecl list) =
          match typeArgs with
          | [] -> other
          | ls ->
              ls
              |> List.map (fun (TyparDecl (_,typarg)) -> typarg.Range)
              |> List.reduce Range.unionRanges
  
      let rangeOfSynPatsElse other (synPats:SynSimplePat list) =
          match synPats with
          | [] -> other
          | ls ->
              ls 
              |> List.map (fun x ->
                      match x with
                      | SynSimplePat.Attrib(range = r)
                      | SynSimplePat.Id(range = r)
                      | SynSimplePat.Typed(range = r) -> r)
              |> List.reduce Range.unionRanges
  
  
      /// Collapse indicates the way a range/snapshot should be collapsed. `Same` is for a scope inside
      /// some kind of scope delimiter, e.g. `[| ... |]`, `[ ... ]`, `{ ... }`, etc.  `Below` is for expressions
      /// following a binding or the right hand side of a pattern, e.g. `let x = ...`
      type Collapse =
          | Below
          | Same
  
      /// Tag to identify the constuct that can be stored alongside its associated ranges
      type Scope =
          | Open
          | Namespace
          | Module
          | Type
          | Member
          | LetOrUse
          | Val
          | CompExpr
          | IfThenElse
          | ThenInIfThenElse
          | ElseInIfThenElse
          | TryWith
          | TryInTryWith
          | WithInTryWith
          | TryFinally
          | TryInTryFinally
          | FinallyInTryFinally
          | ArrayOrList
          | ObjExpr
          | For
          | While
          | Match
          | MatchLambda
          | MatchClause
          | Lambda
          | CompExprInternal
          | Quote
          | Record
          | SpecialFunc
          | Do
          | New
          | Attribute
          | Interface
          | HashDirective
          | LetOrUseBang
          | TypeExtension
          | YieldOrReturn
          | YieldOrReturnBang
          | Tuple
          | UnionCase
          | EnumCase
          | RecordField
          | RecordDefn
          | UnionDefn
          | Comment
          | XmlDocComment
          override self.ToString() = self |> function
              | Open                  -> "Open"
              | Namespace             -> "Namespace"
              | Module                -> "Module"
              | Type                  -> "Type"
              | Member                -> "Member"
              | LetOrUse              -> "LetOrUse"
              | Val                   -> "Val"
              | CompExpr              -> "CompExpr"
              | IfThenElse            -> "IfThenElse"
              | ThenInIfThenElse      -> "ThenInIfThenElse"
              | ElseInIfThenElse      -> "ElseInIfThenElse"
              | TryWith               -> "TryWith"
              | TryInTryWith          -> "TryInTryWith"
              | WithInTryWith         -> "WithInTryWith"
              | TryFinally            -> "TryFinally"
              | TryInTryFinally       -> "TryInTryFinally"
              | FinallyInTryFinally   -> "FinallyInTryFinally"
              | ArrayOrList           -> "ArrayOrList"
              | ObjExpr               -> "ObjExpr"
              | For                   -> "For"
              | While                 -> "While"
              | Match                 -> "Match"
              | MatchLambda           -> "MatchLambda"
              | MatchClause           -> "MatchClause"
              | Lambda                -> "Lambda"
              | CompExprInternal      -> "CompExprInternal"
              | Quote                 -> "Quote"
              | Record                -> "Record"
              | SpecialFunc           -> "SpecialFunc"
              | Do                    -> "Do"
              | New                   -> "New"
              | Attribute             -> "Attribute"
              | Interface             -> "Interface"
              | HashDirective         -> "HashDirective"
              | LetOrUseBang          -> "LetOrUseBang"
              | TypeExtension         -> "TypeExtension"
              | YieldOrReturn         -> "YieldOrReturn"
              | YieldOrReturnBang     -> "YieldOrReturnBang"
              | Tuple                 -> "Tuple"
              | UnionCase             -> "UnionCase"
              | EnumCase              -> "EnumCase"
              | RecordField           -> "RecordField"
              | RecordDefn            -> "RecordDefn"
              | UnionDefn             -> "UnionDefn"
              | Comment               -> "Comment"
              | XmlDocComment         -> "XmlDocComment"
  
      /// Stores the range for a construct, the sub-range that should be collapsed for outlinging,
      /// a tag for the construct type, and a tag for the collapse style
      [<NoComparison>]
      type ScopeRange = {
          Scope: Scope
          Collapse: Collapse
          /// HintSpan in BlockSpan
          Range: range
          /// TextSpan in BlockSpan
          CollapseRange:range
      }
  
      /// Validation function to ensure that ranges yielded for outlinging span 2 or more lines
      let inline private rcheck scope collapse (fullRange:range) (collapseRange:range)  = seq {
          if fullRange.StartLine <> fullRange.EndLine then yield {
              Scope = scope
              Collapse = collapse
              Range = fullRange
              CollapseRange = collapseRange
          }
      }
  
        //============================================//
       //     Implementation File AST Traversal      //
      //============================================//
  
  
      let rec private parseExpr expression =
          seq {
  