From a68786a5a64913026d1205ab1a94ad819668ca50 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Sat, 26 Aug 2023 12:51:19 -0500 Subject: [PATCH] Extract out AST-collecting-walker to a separate function + abstract class (#1154) * extract out AST-collecting-walker to a separate function + abstract class and use it for range aggregation * better factoring of the syntax-walking code --- src/FsAutoComplete.Core/Commands.fs | 2 +- src/FsAutoComplete.Core/UntypedAstUtils.fs | 1235 +++++++++---------- src/FsAutoComplete.Core/UntypedAstUtils.fsi | 107 +- 3 files changed, 692 insertions(+), 652 deletions(-) diff --git a/src/FsAutoComplete.Core/Commands.fs b/src/FsAutoComplete.Core/Commands.fs index 10eb5cea2..3fd723e8e 100644 --- a/src/FsAutoComplete.Core/Commands.fs +++ b/src/FsAutoComplete.Core/Commands.fs @@ -206,7 +206,7 @@ module Commands = let getRangesAtPosition (getParseResultsForFile: _ -> Async>) file positions = asyncResult { let! ast = getParseResultsForFile file - return positions |> List.map (UntypedAstUtils.getRangesAtPosition ast.ParseTree) + return positions |> List.map (FoldingRange.getRangesAtPosition ast.ParseTree) } let scopesForFile diff --git a/src/FsAutoComplete.Core/UntypedAstUtils.fs b/src/FsAutoComplete.Core/UntypedAstUtils.fs index c5801ed2b..029fe8c2c 100644 --- a/src/FsAutoComplete.Core/UntypedAstUtils.fs +++ b/src/FsAutoComplete.Core/UntypedAstUtils.fs @@ -1,668 +1,663 @@ -/// Code from VisualFSharpPowerTools project: https://github.com/fsprojects/VisualFSharpPowerTools/blob/master/src/FSharp.Editing/Common/UntypedAstUtils.fs -module FsAutoComplete.UntypedAstUtils +namespace FSharp.Compiler -open FSharp.Compiler.Syntax -open System.Collections.Generic -open FSharp.Compiler -open FSharp.Compiler.Text -open FSharp.Control.Reactive.Observable +module Syntax = + open FSharp.Compiler.Syntax -type Range with + /// A pattern that collects all attributes from a `SynAttributes` into a single flat list + let (|AllAttrs|) (attrs: SynAttributes) = + attrs |> List.collect (fun attrList -> attrList.Attributes) - member inline x.IsEmpty = x.StartColumn = x.EndColumn && x.StartLine = x.EndLine - -type internal ShortIdent = string -type internal Idents = ShortIdent[] - -let internal longIdentToArray (longIdent: LongIdent) : Idents = - longIdent |> Seq.map string |> Seq.toArray - -/// An recursive pattern that collect all sequential expressions to avoid StackOverflowException -let rec (|Sequentials|_|) = - function - | SynExpr.Sequential(_, _, e, Sequentials es, _) -> Some(e :: es) - | SynExpr.Sequential(_, _, e1, e2, _) -> Some [ e1; e2 ] - | _ -> None - -let (|ConstructorPats|) = - function - | SynArgPats.Pats ps -> ps - | SynArgPats.NamePatPairs(pats = xs) -> xs |> List.map (fun (_, _, pat) -> pat) - -/// matches if the range contains the position -let (|ContainsPos|_|) pos range = - if Range.rangeContainsPos range pos then Some() else None - -/// Active pattern that matches an ident on a given name by the ident's `idText` -let (|Ident|_|) ofName = - function - | SynExpr.Ident ident when ident.idText = ofName -> Some() - | _ -> None - -/// matches if the range contains the position -let (|IdentContainsPos|_|) pos (ident: Ident) = (|ContainsPos|_|) pos ident.idRange - -/// A pattern that collects all attributes from a `SynAttributes` into a single flat list -let (|AllAttrs|) (attrs: SynAttributes) = - attrs |> List.collect (fun attrList -> attrList.Attributes) - -/// A pattern that collects all patterns from a `SynSimplePats` into a single flat list -let (|AllSimplePats|) (pats: SynSimplePats) = - let rec loop acc pat = - match pat with - | SynSimplePats.SimplePats(pats = pats) -> acc @ pats - - loop [] pats - -/// Gives all ranges for current position -let internal getRangesAtPosition input (r: Position) : Range list = - let mutable result = [] - - - let addIfInside (ran: Range) = - let addToResult r = result <- r :: result - - let isInside (ran: Range) = Range.rangeContainsPos ran r - - if isInside ran then - addToResult ran - - - - let rec walkImplFileInput (ParsedImplFileInput(contents = moduleOrNamespaceList)) = - List.iter walkSynModuleOrNamespace moduleOrNamespaceList - - and walkSynModuleOrNamespace (SynModuleOrNamespace(decls = decls; attribs = AllAttrs attrs; range = r)) = - addIfInside r - List.iter walkAttribute attrs - List.iter walkSynModuleDecl decls - - and walkAttribute (attr: SynAttribute) = - addIfInside attr.Range - walkExpr attr.ArgExpr - - and walkTyparDecl (SynTyparDecl(attributes = AllAttrs attrs; Item2 = typar)) = - List.iter walkAttribute attrs - walkTypar typar - - and walkTyparDecls (typars: SynTyparDecls) = - typars.TyparDecls |> List.iter walkTyparDecl - typars.Constraints |> List.iter walkTypeConstraint - - and walkSynValTyparDecls (SynValTyparDecls(typars, _)) = Option.iter walkTyparDecls typars - - and walkTypeConstraint = + /// An recursive pattern that collect all sequential expressions to avoid StackOverflowException + let rec (|Sequentials|_|) = function - | SynTypeConstraint.WhereTyparIsValueType(t, r) - | SynTypeConstraint.WhereTyparIsReferenceType(t, r) - | SynTypeConstraint.WhereTyparIsUnmanaged(t, r) - | SynTypeConstraint.WhereTyparSupportsNull(t, r) - | SynTypeConstraint.WhereTyparIsComparable(t, r) - | SynTypeConstraint.WhereTyparIsEquatable(t, r) -> - addIfInside r - walkTypar t - | SynTypeConstraint.WhereTyparDefaultsToType(t, ty, r) - | SynTypeConstraint.WhereTyparSubtypeOfType(t, ty, r) -> - addIfInside r - walkTypar t - walkType ty - | SynTypeConstraint.WhereTyparIsEnum(t, ts, r) - | SynTypeConstraint.WhereTyparIsDelegate(t, ts, r) -> - addIfInside r - walkTypar t - List.iter walkType ts - | SynTypeConstraint.WhereTyparSupportsMember(t, sign, r) -> - addIfInside r - walkType t - walkMemberSig sign - | SynTypeConstraint.WhereSelfConstrained(t, r) -> - addIfInside r - walkType t + | SynExpr.Sequential(_, _, e, Sequentials es, _) -> Some(e :: es) + | SynExpr.Sequential(_, _, e1, e2, _) -> Some [ e1; e2 ] + | _ -> None - and walkPat = + let (|ConstructorPats|) = function - | SynPat.Tuple(elementPats = pats; range = r) - | SynPat.ArrayOrList(_, pats, r) - | SynPat.Ands(pats, r) -> - addIfInside r - List.iter walkPat pats - | SynPat.Named(ident, _, _, r) -> addIfInside r - | SynPat.Typed(pat, t, r) -> - addIfInside r - walkPat pat - walkType t - | SynPat.Attrib(pat, AllAttrs attrs, r) -> - addIfInside r - walkPat pat + | SynArgPats.Pats ps -> ps + | SynArgPats.NamePatPairs(pats = xs) -> xs |> List.map (fun (_, _, pat) -> pat) + + /// A pattern that collects all patterns from a `SynSimplePats` into a single flat list + let (|AllSimplePats|) (pats: SynSimplePats) = + let rec loop acc pat = + match pat with + | SynSimplePats.SimplePats(pats = pats) -> acc @ pats + + loop [] pats + + type SyntaxCollectorBase() = + abstract WalkSynModuleOrNamespace: SynModuleOrNamespace -> unit + default _.WalkSynModuleOrNamespace m = () + abstract WalkAttribute: SynAttribute -> unit + default _.WalkAttribute a = () + abstract WalkSynModuleDecl: SynModuleDecl -> unit + default _.WalkSynModuleDecl m = () + abstract WalkExpr: SynExpr -> unit + default _.WalkExpr s = () + abstract WalkTypar: SynTypar -> unit + default _.WalkTypar s = () + abstract WalkTyparDecl: SynTyparDecl -> unit + default _.WalkTyparDecl s = () + abstract WalkTypeConstraint: SynTypeConstraint -> unit + default _.WalkTypeConstraint s = () + abstract WalkType: SynType -> unit + default _.WalkType s = () + abstract WalkMemberSig: SynMemberSig -> unit + default _.WalkMemberSig s = () + abstract WalkPat: SynPat -> unit + default _.WalkPat s = () + abstract WalkValTyparDecls: SynValTyparDecls -> unit + default _.WalkValTyparDecls s = () + abstract WalkBinding: SynBinding -> unit + default _.WalkBinding s = () + abstract WalkSimplePat: SynSimplePat -> unit + default _.WalkSimplePat s = () + abstract WalkInterfaceImpl: SynInterfaceImpl -> unit + default _.WalkInterfaceImpl s = () + abstract WalkClause: SynMatchClause -> unit + default _.WalkClause s = () + abstract WalkInterpolatedStringPart: SynInterpolatedStringPart -> unit + default _.WalkInterpolatedStringPart s = () + abstract WalkMeasure: SynMeasure -> unit + default _.WalkMeasure s = () + abstract WalkComponentInfo: SynComponentInfo -> unit + default _.WalkComponentInfo s = () + abstract WalkTypeDefnSigRepr: SynTypeDefnSigRepr -> unit + default _.WalkTypeDefnSigRepr s = () + abstract WalkUnionCaseType: SynUnionCaseKind -> unit + default _.WalkUnionCaseType s = () + abstract WalkEnumCase: SynEnumCase -> unit + default _.WalkEnumCase s = () + abstract WalkField: SynField -> unit + default _.WalkField s = () + abstract WalkTypeDefnSimple: SynTypeDefnSimpleRepr -> unit + default _.WalkTypeDefnSimple s = () + abstract WalkValSig: SynValSig -> unit + default _.WalkValSig s = () + abstract WalkMember: SynMemberDefn -> unit + default _.WalkMember s = () + abstract WalkUnionCase: SynUnionCase -> unit + default _.WalkUnionCase s = () + abstract WalkTypeDefnRepr: SynTypeDefnRepr -> unit + default _.WalkTypeDefnRepr s = () + abstract WalkTypeDefn: SynTypeDefn -> unit + default _.WalkTypeDefn s = () + + let walkAst (walker: SyntaxCollectorBase) (input: ParsedInput) : unit = + + let rec walkImplFileInput (ParsedImplFileInput(contents = moduleOrNamespaceList)) = + List.iter walkSynModuleOrNamespace moduleOrNamespaceList + + and walkSynModuleOrNamespace (SynModuleOrNamespace(decls = decls; attribs = AllAttrs attrs; range = r) as s) = + walker.WalkSynModuleOrNamespace s List.iter walkAttribute attrs - | SynPat.Or(pat1, pat2, r, _) -> - addIfInside r - List.iter walkPat [ pat1; pat2 ] - | SynPat.LongIdent(typarDecls = typars; argPats = ConstructorPats pats; range = r) -> - addIfInside r - Option.iter walkSynValTyparDecls typars - List.iter walkPat pats - | SynPat.Paren(pat, r) -> - addIfInside r - walkPat pat - | SynPat.IsInst(t, r) -> - addIfInside r - walkType t - | SynPat.QuoteExpr(e, r) -> - addIfInside r - walkExpr e - | SynPat.Const(_, r) -> addIfInside r - | SynPat.Wild(r) -> addIfInside r - | SynPat.Record(_, r) -> addIfInside r - | SynPat.Null(r) -> addIfInside r - | SynPat.OptionalVal(_, r) -> addIfInside r - | SynPat.DeprecatedCharRange(_, _, r) -> addIfInside r - | SynPat.InstanceMember(_, _, _, accessibility, r) -> addIfInside r - | SynPat.FromParseError(_, r) -> addIfInside r - | SynPat.As(lpat, rpat, r) -> - addIfInside r - walkPat lpat - walkPat rpat - | SynPat.ListCons(lpat, rpat, r, _) -> - addIfInside r - walkPat lpat - walkPat rpat + List.iter walkSynModuleDecl decls - and walkTypar (SynTypar(_, _, _)) = () + and walkAttribute (attr: SynAttribute) = walkExpr attr.ArgExpr - and walkBinding - (SynBinding(attributes = AllAttrs attrs; headPat = pat; returnInfo = returnInfo; expr = e; range = r)) - = - addIfInside r - List.iter walkAttribute attrs - walkPat pat - walkExpr e + and walkTyparDecl (SynTyparDecl(attributes = AllAttrs attrs; Item2 = typar)) = + List.iter walkAttribute attrs + walkTypar typar + + and walkTyparDecls (typars: SynTyparDecls) = + typars.TyparDecls |> List.iter walkTyparDecl + typars.Constraints |> List.iter walkTypeConstraint + + and walkSynValTyparDecls (SynValTyparDecls(typars, _)) = Option.iter walkTyparDecls typars + + and walkTypeConstraint s = + walker.WalkTypeConstraint s + + match s with + | SynTypeConstraint.WhereTyparIsValueType(t, r) + | SynTypeConstraint.WhereTyparIsReferenceType(t, r) + | SynTypeConstraint.WhereTyparIsUnmanaged(t, r) + | SynTypeConstraint.WhereTyparSupportsNull(t, r) + | SynTypeConstraint.WhereTyparIsComparable(t, r) + | SynTypeConstraint.WhereTyparIsEquatable(t, r) -> walkTypar t + | SynTypeConstraint.WhereTyparDefaultsToType(t, ty, r) + | SynTypeConstraint.WhereTyparSubtypeOfType(t, ty, r) -> + walkTypar t + walkType ty + | SynTypeConstraint.WhereTyparIsEnum(t, ts, r) + | SynTypeConstraint.WhereTyparIsDelegate(t, ts, r) -> + walkTypar t + List.iter walkType ts + | SynTypeConstraint.WhereTyparSupportsMember(t, sign, r) -> + walkType t + walkMemberSig sign + | SynTypeConstraint.WhereSelfConstrained(t, r) -> walkType t + + and walkPat s = + walker.WalkPat s + + match s with + | SynPat.Tuple(elementPats = pats; range = r) + | SynPat.ArrayOrList(_, pats, r) + | SynPat.Ands(pats, r) -> List.iter walkPat pats + | SynPat.Named(ident, _, _, r) -> () + | SynPat.Typed(pat, t, r) -> + walkPat pat + walkType t + | SynPat.Attrib(pat, AllAttrs attrs, r) -> + walkPat pat + List.iter walkAttribute attrs + | SynPat.Or(pat1, pat2, r, _) -> List.iter walkPat [ pat1; pat2 ] + | SynPat.LongIdent(typarDecls = typars; argPats = ConstructorPats pats; range = r) -> + Option.iter walkSynValTyparDecls typars + List.iter walkPat pats + | SynPat.Paren(pat, r) -> walkPat pat + | SynPat.IsInst(t, r) -> walkType t + | SynPat.QuoteExpr(e, r) -> walkExpr e + | SynPat.Const(_, r) -> () + | SynPat.Wild(r) -> () + | SynPat.Record(_, r) -> () + | SynPat.Null(r) -> () + | SynPat.OptionalVal(_, r) -> () + | SynPat.DeprecatedCharRange(_, _, r) -> () + | SynPat.InstanceMember(_, _, _, accessibility, r) -> () + | SynPat.FromParseError(_, r) -> () + | SynPat.As(lpat, rpat, r) -> + walkPat lpat + walkPat rpat + | SynPat.ListCons(lpat, rpat, r, _) -> + walkPat lpat + walkPat rpat + + and walkTypar (SynTypar(_, _, _) as s) = walker.WalkTypar s + + and walkBinding + (SynBinding(attributes = AllAttrs attrs; headPat = pat; returnInfo = returnInfo; expr = e; range = r) as s) + = + walker.WalkBinding s + List.iter walkAttribute attrs + walkPat pat + walkExpr e - returnInfo - |> Option.iter (fun (SynBindingReturnInfo(t, r, attrs, _)) -> - addIfInside r - walkType t - walkAttributes attrs) + returnInfo + |> Option.iter (fun (SynBindingReturnInfo(t, r, attrs, _)) -> + walkType t + walkAttributes attrs) - and walkAttributes (attrs: SynAttributes) = - List.iter - (fun (attrList: SynAttributeList) -> - addIfInside attrList.Range - List.iter walkAttribute attrList.Attributes) - attrs + and walkAttributes (attrs: SynAttributes) = + List.iter (fun (attrList: SynAttributeList) -> List.iter walkAttribute attrList.Attributes) attrs - and walkInterfaceImpl (SynInterfaceImpl(bindings = bindings; range = r)) = - addIfInside r - List.iter walkBinding bindings + and walkInterfaceImpl (SynInterfaceImpl(bindings = bindings; range = r) as s) = + walker.WalkInterfaceImpl s + List.iter walkBinding bindings - and walkType = - function - | SynType.Array(_, t, r) - | SynType.HashConstraint(t, r) - | SynType.MeasurePower(t, _, r) -> - addIfInside r + and walkType s = + walker.WalkType s + + match s with + | SynType.Array(_, t, r) + | SynType.HashConstraint(t, r) + | SynType.MeasurePower(t, _, r) -> walkType t + | SynType.Fun(t1, t2, r, _) -> + // | SynType.MeasureDivide(t1, t2, r) -> + walkType t1 + walkType t2 + | SynType.App(ty, _, types, _, _, _, r) -> + walkType ty + List.iter walkType types + | SynType.LongIdentApp(_, _, _, types, _, _, r) -> List.iter walkType types + | SynType.Tuple(_, ts, r) -> + ts + |> List.iter (function + | SynTupleTypeSegment.Type t -> walkType t + | _ -> ()) + | SynType.WithGlobalConstraints(t, typeConstraints, r) -> + walkType t + List.iter walkTypeConstraint typeConstraints + | SynType.LongIdent(longDotId) -> () + | SynType.AnonRecd(isStruct, typeNames, r) -> () + | SynType.Var(genericName, r) -> () + | SynType.Anon(r) -> () + | SynType.StaticConstant(constant, r) -> () + | SynType.StaticConstantExpr(expr, r) -> () + | SynType.StaticConstantNamed(expr, _, r) -> () + | SynType.Paren(innerType, r) -> walkType innerType + | SynType.SignatureParameter(usedType = t; range = r) -> walkType t + | SynType.Or(lhs, rhs, r, _) -> + walkType lhs + walkType rhs + | SynType.FromParseError(r) -> () + + and walkClause (SynMatchClause(pat, e1, e2, r, _, _) as s) = + walker.WalkClause s + walkPat pat + walkExpr e2 + e1 |> Option.iter walkExpr + + and walkSimplePats = + function + | SynSimplePats.SimplePats(pats = pats; range = r) -> List.iter walkSimplePat pats + + and walkInterpolatedStringPart s = + walker.WalkInterpolatedStringPart s + + match s with + | SynInterpolatedStringPart.FillExpr(expr, ident) -> walkExpr expr + | SynInterpolatedStringPart.String(s, r) -> () + + and walkExpr s = + walker.WalkExpr s + + match s with + | SynExpr.Typed(e, _, r) -> walkExpr e + | SynExpr.Paren(e, _, _, r) + | SynExpr.Quote(_, _, e, _, r) + | SynExpr.InferredUpcast(e, r) + | SynExpr.InferredDowncast(e, r) + | SynExpr.AddressOf(_, e, _, r) + | SynExpr.DoBang(e, r) + | SynExpr.YieldOrReturn(_, e, r) + | SynExpr.ArrayOrListComputed(_, e, r) + | SynExpr.ComputationExpr(_, e, r) + | SynExpr.Do(e, r) + | SynExpr.Assert(e, r) + | SynExpr.Lazy(e, r) + | SynExpr.YieldOrReturnFrom(_, e, r) -> walkExpr e + | SynExpr.SequentialOrImplicitYield(_, e1, e2, ifNotE, r) -> + walkExpr e1 + walkExpr e2 + walkExpr ifNotE + | SynExpr.Lambda(args = pats; body = e; range = r) -> + walkSimplePats pats + walkExpr e + | SynExpr.New(_, t, e, r) + | SynExpr.TypeTest(e, t, r) + | SynExpr.Upcast(e, t, r) + | SynExpr.Downcast(e, t, r) -> + walkExpr e + walkType t + | SynExpr.Tuple(_, es, _, _) + | Sequentials es -> List.iter walkExpr es //TODO?? + | SynExpr.ArrayOrList(_, es, r) -> List.iter walkExpr es + | SynExpr.App(_, _, e1, e2, r) + | SynExpr.TryFinally(e1, e2, r, _, _, _) + | SynExpr.While(_, e1, e2, r) -> List.iter walkExpr [ e1; e2 ] + | SynExpr.Record(_, _, fields, r) -> + + fields + |> List.iter (fun (SynExprRecordField(fieldName = (ident, _); expr = e)) -> e |> Option.iter walkExpr) + | SynExpr.ObjExpr(ty, argOpt, _, bindings, _, ifaces, _, r) -> + + argOpt |> Option.iter (fun (e, ident) -> walkExpr e) + + walkType ty + List.iter walkBinding bindings + List.iter walkInterfaceImpl ifaces + | SynExpr.For(identBody = e1; toBody = e2; doBody = e3; range = r) -> List.iter walkExpr [ e1; e2; e3 ] + | SynExpr.ForEach(_, _, _, _, pat, e1, e2, r) -> + walkPat pat + List.iter walkExpr [ e1; e2 ] + | SynExpr.MatchLambda(_, _, synMatchClauseList, _, r) -> List.iter walkClause synMatchClauseList + | SynExpr.Match(expr = e; clauses = synMatchClauseList; range = r) -> + walkExpr e + List.iter walkClause synMatchClauseList + | SynExpr.TypeApp(e, _, tys, _, _, tr, r) -> + List.iter walkType tys + walkExpr e + | SynExpr.LetOrUse(bindings = bindings; body = e; range = r) -> + List.iter walkBinding bindings + walkExpr e + | SynExpr.TryWith(tryExpr = e; withCases = clauses; range = r) -> + List.iter walkClause clauses + walkExpr e + | SynExpr.IfThenElse(ifExpr = e1; thenExpr = e2; elseExpr = e3; range = r) -> + List.iter walkExpr [ e1; e2 ] + e3 |> Option.iter walkExpr + | SynExpr.LongIdentSet(ident, e, r) + | SynExpr.DotGet(e, _, ident, r) -> walkExpr e + | SynExpr.DotSet(e1, idents, e2, r) -> + walkExpr e1 + walkExpr e2 + | SynExpr.DotIndexedGet(e, args, _, r) -> + walkExpr e + walkExpr args + | SynExpr.DotIndexedSet(e1, args, e2, _, _, r) -> + walkExpr e1 + walkExpr args + walkExpr e2 + | SynExpr.NamedIndexedPropertySet(ident, e1, e2, r) -> List.iter walkExpr [ e1; e2 ] + | SynExpr.DotNamedIndexedPropertySet(e1, ident, e2, e3, r) -> List.iter walkExpr [ e1; e2; e3 ] + | SynExpr.JoinIn(e1, _, e2, r) -> List.iter walkExpr [ e1; e2 ] + | SynExpr.LetOrUseBang(pat = pat; rhs = e1; andBangs = ands; body = e2; range = r) -> + walkPat pat + walkExpr e1 + + for (SynExprAndBang(pat = pat; body = body; range = r)) in ands do + walkPat pat + walkExpr body + + walkExpr e2 + | SynExpr.TraitCall(t, sign, e, r) -> + walkType t + walkMemberSig sign + walkExpr e + | SynExpr.Const(SynConst.Measure(_, _, m), r) -> walkMeasure m + | SynExpr.Const(_, r) -> () + | SynExpr.AnonRecd(isStruct, copyInfo, recordFields, r, trivia) -> () + | SynExpr.Sequential(seqPoint, isTrueSeq, expr1, expr2, r) -> () + | SynExpr.Ident(_) -> () + | SynExpr.LongIdent(isOptional, longDotId, altNameRefCell, r) -> () + | SynExpr.Set(_, _, r) -> () + | SynExpr.Null(r) -> () + | SynExpr.ImplicitZero(r) -> () + | SynExpr.MatchBang(range = r) -> () + | SynExpr.LibraryOnlyILAssembly(_, _, _, _, r) -> () + | SynExpr.LibraryOnlyStaticOptimization(_, _, _, r) -> () + | SynExpr.LibraryOnlyUnionCaseFieldGet(expr, longId, _, r) -> () + | SynExpr.LibraryOnlyUnionCaseFieldSet(_, longId, _, _, r) -> () + | SynExpr.ArbitraryAfterError(debugStr, r) -> () + | SynExpr.FromParseError(expr, r) -> () + | SynExpr.DiscardAfterMissingQualificationAfterDot(_, _, r) -> () + | SynExpr.Fixed(expr, r) -> () + | SynExpr.InterpolatedString(parts, kind, r) -> + + for part in parts do + walkInterpolatedStringPart part + | SynExpr.IndexFromEnd(itemExpr, r) -> walkExpr itemExpr + | SynExpr.IndexRange(e1, _, e2, _, _, r) -> + Option.iter walkExpr e1 + Option.iter walkExpr e2 + | SynExpr.DebugPoint(innerExpr = expr) -> walkExpr expr + | SynExpr.Dynamic(funcExpr = e1; argExpr = e2; range = range) -> + walkExpr e1 + walkExpr e2 + | SynExpr.Typar(t, r) -> walkTypar t + + and walkMeasure s = + walker.WalkMeasure s + + match s with + | SynMeasure.Product(m1, m2, r) + | SynMeasure.Divide(m1, m2, r) -> + walkMeasure m1 + walkMeasure m2 + | SynMeasure.Named(longIdent, r) -> () + | SynMeasure.Seq(ms, r) -> List.iter walkMeasure ms + | SynMeasure.Power(m, _, r) -> walkMeasure m + | SynMeasure.Var(ty, r) -> walkTypar ty + | SynMeasure.Paren(m, r) -> walkMeasure m + | SynMeasure.One + | SynMeasure.Anon _ -> () + + and walkSimplePat s = + walker.WalkSimplePat s + + match s with + | SynSimplePat.Attrib(pat, AllAttrs attrs, r) -> + walkSimplePat pat + List.iter walkAttribute attrs + | SynSimplePat.Typed(pat, t, r) -> + walkSimplePat pat + walkType t + | SynSimplePat.Id(ident, altNameRefCell, isCompilerGenerated, isThisVar, isOptArg, r) -> () + + and walkField (SynField(attributes = AllAttrs attrs; fieldType = t; range = r) as s) = + walker.WalkField s + List.iter walkAttribute attrs walkType t - | SynType.Fun(t1, t2, r, _) -> - // | SynType.MeasureDivide(t1, t2, r) -> - addIfInside r - walkType t1 - walkType t2 - | SynType.App(ty, _, types, _, _, _, r) -> - addIfInside r - walkType ty - List.iter walkType types - | SynType.LongIdentApp(_, _, _, types, _, _, r) -> - addIfInside r - List.iter walkType types - | SynType.Tuple(_, ts, r) -> - addIfInside r - ts - |> List.iter (function - | SynTupleTypeSegment.Type t -> walkType t - | _ -> ()) - | SynType.WithGlobalConstraints(t, typeConstraints, r) -> - addIfInside r - walkType t - List.iter walkTypeConstraint typeConstraints - | SynType.LongIdent(longDotId) -> () - | SynType.AnonRecd(isStruct, typeNames, r) -> addIfInside r - | SynType.Var(genericName, r) -> addIfInside r - | SynType.Anon(r) -> addIfInside r - | SynType.StaticConstant(constant, r) -> addIfInside r - | SynType.StaticConstantExpr(expr, r) -> addIfInside r - | SynType.StaticConstantNamed(expr, _, r) -> addIfInside r - | SynType.Paren(innerType, r) -> - addIfInside r - walkType innerType - | SynType.SignatureParameter(usedType = t; range = r) -> - addIfInside r + and walkValSig + (SynValSig(attributes = AllAttrs attrs; synType = t; arity = SynValInfo(argInfos, argInfo); range = r) as s) + = + walker.WalkValSig s + List.iter walkAttribute attrs walkType t - | SynType.Or(lhs, rhs, r, _) -> - addIfInside r - walkType lhs - walkType rhs - | SynType.FromParseError(r) -> addIfInside r - and walkClause (SynMatchClause(pat, e1, e2, r, _, _)) = - addIfInside r - walkPat pat - walkExpr e2 - e1 |> Option.iter walkExpr + argInfo :: (argInfos |> List.concat) + |> List.collect (fun (SynArgInfo(attributes = AllAttrs attrs)) -> attrs) + |> List.iter walkAttribute + + and walkMemberSig s = + walker.WalkMemberSig s + + match s with + | SynMemberSig.Inherit(t, r) + | SynMemberSig.Interface(t, r) -> walkType t + | SynMemberSig.Member(vs, _, r, _) -> walkValSig vs + | SynMemberSig.ValField(f, r) -> walkField f + | SynMemberSig.NestedType(SynTypeDefnSig(typeInfo = info; typeRepr = repr; members = memberSigs), r) -> + + let isTypeExtensionOrAlias = + match repr with + | SynTypeDefnSigRepr.Simple(SynTypeDefnSimpleRepr.TypeAbbrev _, _) + | SynTypeDefnSigRepr.ObjectModel(SynTypeDefnKind.Abbrev, _, _) + | SynTypeDefnSigRepr.ObjectModel(SynTypeDefnKind.Augmentation _, _, _) -> true + | _ -> false + + walkComponentInfo isTypeExtensionOrAlias info + walkTypeDefnSigRepr repr + List.iter walkMemberSig memberSigs + + and walkMember s = + walker.WalkMember s + + match s with + | SynMemberDefn.AbstractSlot(valSig, _, r, _) -> walkValSig valSig + | SynMemberDefn.Member(binding, r) -> walkBinding binding + | SynMemberDefn.ImplicitCtor(_, AllAttrs attrs, AllSimplePats pats, _, _, r, _) -> + List.iter walkAttribute attrs + List.iter walkSimplePat pats + | SynMemberDefn.ImplicitInherit(t, e, _, r) -> + walkType t + walkExpr e + | SynMemberDefn.LetBindings(bindings, _, _, r) -> List.iter walkBinding bindings + | SynMemberDefn.Interface(t, _, members, r) -> + walkType t + members |> Option.iter (List.iter walkMember) + | SynMemberDefn.Inherit(t, _, r) -> walkType t + | SynMemberDefn.ValField(field, r) -> walkField field + | SynMemberDefn.NestedType(tdef, _, r) -> walkTypeDefn tdef + | SynMemberDefn.AutoProperty(attributes = AllAttrs attrs; typeOpt = t; synExpr = e; range = r) -> + List.iter walkAttribute attrs + Option.iter walkType t + walkExpr e + | SynMemberDefn.Open(longId, r) -> () + | SynMemberDefn.GetSetMember(memberDefnForGet = getter; memberDefnForSet = setter; range = range) -> + Option.iter walkBinding getter + Option.iter walkBinding setter + + and walkEnumCase (SynEnumCase(attributes = AllAttrs attrs; range = r) as s) = + walker.WalkEnumCase s + List.iter walkAttribute attrs - and walkSimplePats = - function - | SynSimplePats.SimplePats(pats = pats; range = r) -> - addIfInside r - List.iter walkSimplePat pats + and walkUnionCaseType s = + walker.WalkUnionCaseType s - and walkInterpolatedStringPart = - function - | SynInterpolatedStringPart.FillExpr(expr, ident) -> - ident |> Option.iter (fun ident -> addIfInside ident.idRange) + match s with + | SynUnionCaseKind.Fields fields -> List.iter walkField fields + | SynUnionCaseKind.FullType(t, _) -> walkType t - walkExpr expr - | SynInterpolatedStringPart.String(s, r) -> addIfInside r + and walkUnionCase (SynUnionCase(attributes = AllAttrs attrs; caseType = t; range = r) as s) = + walker.WalkUnionCase s + List.iter walkAttribute attrs + walkUnionCaseType t + + and walkTypeDefnSimple s = + walker.WalkTypeDefnSimple s + + match s with + | SynTypeDefnSimpleRepr.Enum(cases, r) -> List.iter walkEnumCase cases + | SynTypeDefnSimpleRepr.Union(_, cases, r) -> List.iter walkUnionCase cases + | SynTypeDefnSimpleRepr.Record(_, fields, r) -> List.iter walkField fields + | SynTypeDefnSimpleRepr.TypeAbbrev(_, t, r) -> walkType t + | SynTypeDefnSimpleRepr.General(_, _, _, _, _, _, _, r) -> () + | SynTypeDefnSimpleRepr.LibraryOnlyILAssembly(_, r) -> () + | SynTypeDefnSimpleRepr.None(r) -> () + | SynTypeDefnSimpleRepr.Exception(_) -> () + + and walkComponentInfo + isTypeExtensionOrAlias + (SynComponentInfo( + attributes = AllAttrs attrs; typeParams = typars; constraints = constraints; longId = longIdent; range = r) as s) + = + walker.WalkComponentInfo s + List.iter walkAttribute attrs + Option.iter walkTyparDecls typars + List.iter walkTypeConstraint constraints - and walkExpr = - function - | SynExpr.Typed(e, _, r) -> - addIfInside r - walkExpr e - | SynExpr.Paren(e, _, _, r) - | SynExpr.Quote(_, _, e, _, r) - | SynExpr.InferredUpcast(e, r) - | SynExpr.InferredDowncast(e, r) - | SynExpr.AddressOf(_, e, _, r) - | SynExpr.DoBang(e, r) - | SynExpr.YieldOrReturn(_, e, r) - | SynExpr.ArrayOrListComputed(_, e, r) - | SynExpr.ComputationExpr(_, e, r) - | SynExpr.Do(e, r) - | SynExpr.Assert(e, r) - | SynExpr.Lazy(e, r) - | SynExpr.YieldOrReturnFrom(_, e, r) -> - addIfInside r - walkExpr e - | SynExpr.SequentialOrImplicitYield(_, e1, e2, ifNotE, r) -> - addIfInside r - walkExpr e1 - walkExpr e2 - walkExpr ifNotE - | SynExpr.Lambda(args = pats; body = e; range = r) -> - addIfInside r - walkSimplePats pats - walkExpr e - | SynExpr.New(_, t, e, r) - | SynExpr.TypeTest(e, t, r) - | SynExpr.Upcast(e, t, r) - | SynExpr.Downcast(e, t, r) -> - addIfInside r - walkExpr e - walkType t - | SynExpr.Tuple(_, es, _, _) - | Sequentials es -> List.iter walkExpr es //TODO?? - | SynExpr.ArrayOrList(_, es, r) -> - addIfInside r - List.iter walkExpr es - | SynExpr.App(_, _, e1, e2, r) - | SynExpr.TryFinally(e1, e2, r, _, _, _) - | SynExpr.While(_, e1, e2, r) -> - addIfInside r - List.iter walkExpr [ e1; e2 ] - | SynExpr.Record(_, _, fields, r) -> - addIfInside r + and walkTypeDefnRepr s = + walker.WalkTypeDefnRepr s - fields - |> List.iter (fun (SynExprRecordField(fieldName = (ident, _); expr = e)) -> e |> Option.iter walkExpr) - | SynExpr.ObjExpr(ty, argOpt, _, bindings, _, ifaces, _, r) -> - addIfInside r + match s with + | SynTypeDefnRepr.ObjectModel(_, defns, r) -> List.iter walkMember defns + | SynTypeDefnRepr.Simple(defn, r) -> walkTypeDefnSimple defn + | SynTypeDefnRepr.Exception _ -> () - argOpt |> Option.iter (fun (e, ident) -> walkExpr e) + and walkTypeDefnSigRepr s = + walker.WalkTypeDefnSigRepr s - walkType ty - List.iter walkBinding bindings - List.iter walkInterfaceImpl ifaces - | SynExpr.For(identBody = e1; toBody = e2; doBody = e3; range = r) -> - addIfInside r - List.iter walkExpr [ e1; e2; e3 ] - | SynExpr.ForEach(_, _, _, _, pat, e1, e2, r) -> - addIfInside r - walkPat pat - List.iter walkExpr [ e1; e2 ] - | SynExpr.MatchLambda(_, _, synMatchClauseList, _, r) -> - addIfInside r - List.iter walkClause synMatchClauseList - | SynExpr.Match(expr = e; clauses = synMatchClauseList; range = r) -> - addIfInside r - walkExpr e - List.iter walkClause synMatchClauseList - | SynExpr.TypeApp(e, _, tys, _, _, tr, r) -> - addIfInside tr - addIfInside r - List.iter walkType tys - walkExpr e - | SynExpr.LetOrUse(bindings = bindings; body = e; range = r) -> - addIfInside r - List.iter walkBinding bindings - walkExpr e - | SynExpr.TryWith(tryExpr = e; withCases = clauses; range = r) -> - addIfInside r - List.iter walkClause clauses - walkExpr e - | SynExpr.IfThenElse(ifExpr = e1; thenExpr = e2; elseExpr = e3; range = r) -> - addIfInside r - List.iter walkExpr [ e1; e2 ] - e3 |> Option.iter walkExpr - | SynExpr.LongIdentSet(ident, e, r) - | SynExpr.DotGet(e, _, ident, r) -> - addIfInside r - walkExpr e - | SynExpr.DotSet(e1, idents, e2, r) -> - addIfInside r - walkExpr e1 - walkExpr e2 - | SynExpr.DotIndexedGet(e, args, _, r) -> - addIfInside r - walkExpr e - walkExpr args - | SynExpr.DotIndexedSet(e1, args, e2, _, _, r) -> - addIfInside r - walkExpr e1 - walkExpr args - walkExpr e2 - | SynExpr.NamedIndexedPropertySet(ident, e1, e2, r) -> - addIfInside r - List.iter walkExpr [ e1; e2 ] - | SynExpr.DotNamedIndexedPropertySet(e1, ident, e2, e3, r) -> - addIfInside r - List.iter walkExpr [ e1; e2; e3 ] - | SynExpr.JoinIn(e1, _, e2, r) -> - addIfInside r - List.iter walkExpr [ e1; e2 ] - | SynExpr.LetOrUseBang(pat = pat; rhs = e1; andBangs = ands; body = e2; range = r) -> - addIfInside r - walkPat pat - walkExpr e1 + match s with + | SynTypeDefnSigRepr.ObjectModel(_, defns, _) -> List.iter walkMemberSig defns + | SynTypeDefnSigRepr.Simple(defn, _) -> walkTypeDefnSimple defn + | SynTypeDefnSigRepr.Exception _ -> () - for (SynExprAndBang(pat = pat; body = body; range = r)) in ands do - addIfInside r - walkPat pat - walkExpr body + and walkTypeDefn (SynTypeDefn(info, repr, members, implicitCtor, r, _) as s) = + walker.WalkTypeDefn s - walkExpr e2 - | SynExpr.TraitCall(t, sign, e, r) -> - addIfInside r - walkType t - walkMemberSig sign - walkExpr e - | SynExpr.Const(SynConst.Measure(_, _, m), r) -> - addIfInside r - walkMeasure m - | SynExpr.Const(_, r) -> addIfInside r - | SynExpr.AnonRecd(isStruct, copyInfo, recordFields, r, trivia) -> addIfInside r - | SynExpr.Sequential(seqPoint, isTrueSeq, expr1, expr2, r) -> () - | SynExpr.Ident(_) -> () - | SynExpr.LongIdent(isOptional, longDotId, altNameRefCell, r) -> addIfInside r - | SynExpr.Set(_, _, r) -> addIfInside r - | SynExpr.Null(r) -> addIfInside r - | SynExpr.ImplicitZero(r) -> addIfInside r - | SynExpr.MatchBang(range = r) -> addIfInside r - | SynExpr.LibraryOnlyILAssembly(_, _, _, _, r) -> addIfInside r - | SynExpr.LibraryOnlyStaticOptimization(_, _, _, r) -> addIfInside r - | SynExpr.LibraryOnlyUnionCaseFieldGet(expr, longId, _, r) -> addIfInside r - | SynExpr.LibraryOnlyUnionCaseFieldSet(_, longId, _, _, r) -> addIfInside r - | SynExpr.ArbitraryAfterError(debugStr, r) -> addIfInside r - | SynExpr.FromParseError(expr, r) -> addIfInside r - | SynExpr.DiscardAfterMissingQualificationAfterDot(_, _, r) -> addIfInside r - | SynExpr.Fixed(expr, r) -> addIfInside r - | SynExpr.InterpolatedString(parts, kind, r) -> - addIfInside r + let isTypeExtensionOrAlias = + match repr with + | SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Augmentation _, _, _) + | SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Abbrev, _, _) + | SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.TypeAbbrev _, _) -> true + | _ -> false - for part in parts do - walkInterpolatedStringPart part - | SynExpr.IndexFromEnd(itemExpr, r) -> - addIfInside r - walkExpr itemExpr - | SynExpr.IndexRange(e1, _, e2, _, _, r) -> - addIfInside r - Option.iter walkExpr e1 - Option.iter walkExpr e2 - | SynExpr.DebugPoint(innerExpr = expr) -> walkExpr expr - | SynExpr.Dynamic(funcExpr = e1; argExpr = e2; range = range) -> - addIfInside range - walkExpr e1 - walkExpr e2 - | SynExpr.Typar(t, r) -> - addIfInside r - walkTypar t + walkComponentInfo isTypeExtensionOrAlias info + walkTypeDefnRepr repr + Option.iter walkMember implicitCtor + List.iter walkMember members - and walkMeasure = - function - | SynMeasure.Product(m1, m2, r) - | SynMeasure.Divide(m1, m2, r) -> - addIfInside r - walkMeasure m1 - walkMeasure m2 - | SynMeasure.Named(longIdent, r) -> addIfInside r - | SynMeasure.Seq(ms, r) -> - addIfInside r - List.iter walkMeasure ms - | SynMeasure.Power(m, _, r) -> - addIfInside r - walkMeasure m - | SynMeasure.Var(ty, r) -> - addIfInside r - walkTypar ty - | SynMeasure.Paren(m, r) -> - addIfInside r - walkMeasure m - | SynMeasure.One - | SynMeasure.Anon _ -> () + and walkSynModuleDecl (decl: SynModuleDecl) = + walker.WalkSynModuleDecl decl - and walkSimplePat = - function - | SynSimplePat.Attrib(pat, AllAttrs attrs, r) -> - addIfInside r - walkSimplePat pat - List.iter walkAttribute attrs - | SynSimplePat.Typed(pat, t, r) -> - addIfInside r - walkSimplePat pat - walkType t - | SynSimplePat.Id(ident, altNameRefCell, isCompilerGenerated, isThisVar, isOptArg, r) -> addIfInside r + match decl with + | SynModuleDecl.NamespaceFragment fragment -> walkSynModuleOrNamespace fragment + | SynModuleDecl.NestedModule(info, _, modules, _, r, _) -> + walkComponentInfo false info + List.iter walkSynModuleDecl modules + | SynModuleDecl.Let(_, bindings, r) -> List.iter walkBinding bindings + | SynModuleDecl.Expr(expr, r) -> walkExpr expr + | SynModuleDecl.Types(types, r) -> List.iter walkTypeDefn types + | SynModuleDecl.Attributes(attributes = AllAttrs attrs; range = r) -> List.iter walkAttribute attrs + | SynModuleDecl.ModuleAbbrev(ident, longId, r) -> () + | SynModuleDecl.Exception(_, r) -> () + | SynModuleDecl.Open(longDotId, r) -> () + | SynModuleDecl.HashDirective(_, r) -> () + match input with + | ParsedInput.ImplFile input -> walkImplFileInput input + | _ -> () - and walkField (SynField(attributes = AllAttrs attrs; fieldType = t; range = r)) = - addIfInside r - List.iter walkAttribute attrs - walkType t +namespace FsAutoComplete - and walkValSig - (SynValSig(attributes = AllAttrs attrs; synType = t; arity = SynValInfo(argInfos, argInfo); range = r)) - = - addIfInside r - List.iter walkAttribute attrs - walkType t +module UntypedAstUtils = - argInfo :: (argInfos |> List.concat) - |> List.collect (fun (SynArgInfo(attributes = AllAttrs attrs)) -> attrs) - |> List.iter walkAttribute + open FSharp.Compiler.Syntax + open System.Collections.Generic + open FSharp.Compiler + open FSharp.Compiler.Text + open FSharp.Control.Reactive.Observable - and walkMemberSig = - function - | SynMemberSig.Inherit(t, r) - | SynMemberSig.Interface(t, r) -> - addIfInside r - walkType t - | SynMemberSig.Member(vs, _, r, _) -> - addIfInside r - walkValSig vs - | SynMemberSig.ValField(f, r) -> - addIfInside r - walkField f - | SynMemberSig.NestedType(SynTypeDefnSig(typeInfo = info; typeRepr = repr; members = memberSigs), r) -> - addIfInside r + type Range with - let isTypeExtensionOrAlias = - match repr with - | SynTypeDefnSigRepr.Simple(SynTypeDefnSimpleRepr.TypeAbbrev _, _) - | SynTypeDefnSigRepr.ObjectModel(SynTypeDefnKind.Abbrev, _, _) - | SynTypeDefnSigRepr.ObjectModel(SynTypeDefnKind.Augmentation _, _, _) -> true - | _ -> false + member inline x.IsEmpty = x.StartColumn = x.EndColumn && x.StartLine = x.EndLine - walkComponentInfo isTypeExtensionOrAlias info - walkTypeDefnSigRepr repr - List.iter walkMemberSig memberSigs + type internal ShortIdent = string + type internal Idents = ShortIdent[] - and walkMember = - function - | SynMemberDefn.AbstractSlot(valSig, _, r, _) -> - addIfInside r - walkValSig valSig - | SynMemberDefn.Member(binding, r) -> - addIfInside r - walkBinding binding - | SynMemberDefn.ImplicitCtor(_, AllAttrs attrs, AllSimplePats pats, _, _, r, _) -> - addIfInside r - List.iter walkAttribute attrs - List.iter walkSimplePat pats - | SynMemberDefn.ImplicitInherit(t, e, _, r) -> - addIfInside r - walkType t - walkExpr e - | SynMemberDefn.LetBindings(bindings, _, _, r) -> - addIfInside r - List.iter walkBinding bindings - | SynMemberDefn.Interface(t, _, members, r) -> - addIfInside r - walkType t - members |> Option.iter (List.iter walkMember) - | SynMemberDefn.Inherit(t, _, r) -> - addIfInside r - walkType t - | SynMemberDefn.ValField(field, r) -> - addIfInside r - walkField field - | SynMemberDefn.NestedType(tdef, _, r) -> - addIfInside r - walkTypeDefn tdef - | SynMemberDefn.AutoProperty(attributes = AllAttrs attrs; typeOpt = t; synExpr = e; range = r) -> - addIfInside r - List.iter walkAttribute attrs - Option.iter walkType t - walkExpr e - | SynMemberDefn.Open(longId, r) -> addIfInside r - | SynMemberDefn.GetSetMember(memberDefnForGet = getter; memberDefnForSet = setter; range = range) -> - addIfInside range - Option.iter walkBinding getter - Option.iter walkBinding setter + let internal longIdentToArray (longIdent: LongIdent) : Idents = + longIdent |> Seq.map string |> Seq.toArray - and walkEnumCase (SynEnumCase(attributes = AllAttrs attrs; range = r)) = - addIfInside r - List.iter walkAttribute attrs + /// matches if the range contains the position + let (|ContainsPos|_|) pos range = + if Range.rangeContainsPos range pos then Some() else None - and walkUnionCaseType = + /// Active pattern that matches an ident on a given name by the ident's `idText` + let (|Ident|_|) ofName = function - | SynUnionCaseKind.Fields fields -> List.iter walkField fields - | SynUnionCaseKind.FullType(t, _) -> walkType t - - and walkUnionCase (SynUnionCase(attributes = AllAttrs attrs; caseType = t; range = r)) = - addIfInside r - List.iter walkAttribute attrs - walkUnionCaseType t + | SynExpr.Ident ident when ident.idText = ofName -> Some() + | _ -> None - and walkTypeDefnSimple = - function - | SynTypeDefnSimpleRepr.Enum(cases, r) -> - addIfInside r - List.iter walkEnumCase cases - | SynTypeDefnSimpleRepr.Union(_, cases, r) -> - addIfInside r - List.iter walkUnionCase cases - | SynTypeDefnSimpleRepr.Record(_, fields, r) -> - addIfInside r - List.iter walkField fields - | SynTypeDefnSimpleRepr.TypeAbbrev(_, t, r) -> - addIfInside r - walkType t - | SynTypeDefnSimpleRepr.General(_, _, _, _, _, _, _, r) -> addIfInside r - | SynTypeDefnSimpleRepr.LibraryOnlyILAssembly(_, r) -> addIfInside r - | SynTypeDefnSimpleRepr.None(r) -> addIfInside r - | SynTypeDefnSimpleRepr.Exception(_) -> () - - and walkComponentInfo - isTypeExtensionOrAlias - (SynComponentInfo( - attributes = AllAttrs attrs; typeParams = typars; constraints = constraints; longId = longIdent; range = r)) - = - addIfInside r - List.iter walkAttribute attrs - Option.iter walkTyparDecls typars - List.iter walkTypeConstraint constraints - - and walkTypeDefnRepr = - function - | SynTypeDefnRepr.ObjectModel(_, defns, r) -> - addIfInside r - List.iter walkMember defns - | SynTypeDefnRepr.Simple(defn, r) -> - addIfInside r - walkTypeDefnSimple defn - | SynTypeDefnRepr.Exception _ -> () + /// matches if the range contains the position + let (|IdentContainsPos|_|) pos (ident: Ident) = (|ContainsPos|_|) pos ident.idRange - and walkTypeDefnSigRepr = - function - | SynTypeDefnSigRepr.ObjectModel(_, defns, _) -> List.iter walkMemberSig defns - | SynTypeDefnSigRepr.Simple(defn, _) -> walkTypeDefnSimple defn - | SynTypeDefnSigRepr.Exception _ -> () - - and walkTypeDefn (SynTypeDefn(info, repr, members, implicitCtor, r, _)) = - addIfInside r - - let isTypeExtensionOrAlias = - match repr with - | SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Augmentation _, _, _) - | SynTypeDefnRepr.ObjectModel(SynTypeDefnKind.Abbrev, _, _) - | SynTypeDefnRepr.Simple(SynTypeDefnSimpleRepr.TypeAbbrev _, _) -> true - | _ -> false - - walkComponentInfo isTypeExtensionOrAlias info - walkTypeDefnRepr repr - Option.iter walkMember implicitCtor - List.iter walkMember members - - and walkSynModuleDecl (decl: SynModuleDecl) = - match decl with - | SynModuleDecl.NamespaceFragment fragment -> walkSynModuleOrNamespace fragment - | SynModuleDecl.NestedModule(info, _, modules, _, r, _) -> - addIfInside r - walkComponentInfo false info - List.iter walkSynModuleDecl modules - | SynModuleDecl.Let(_, bindings, r) -> - addIfInside r - List.iter walkBinding bindings - | SynModuleDecl.Expr(expr, r) -> - addIfInside r - walkExpr expr - | SynModuleDecl.Types(types, r) -> - addIfInside r - List.iter walkTypeDefn types - | SynModuleDecl.Attributes(attributes = AllAttrs attrs; range = r) -> - addIfInside r - List.iter walkAttribute attrs - | SynModuleDecl.ModuleAbbrev(ident, longId, r) -> addIfInside r - | SynModuleDecl.Exception(_, r) -> addIfInside r - | SynModuleDecl.Open(longDotId, r) -> addIfInside r - | SynModuleDecl.HashDirective(_, r) -> addIfInside r +module FoldingRange = + open FSharp.Compiler.Text + open FSharp.Compiler.Syntax - match input with - | ParsedInput.ImplFile input -> walkImplFileInput input - | _ -> () - //debug "%A" idents - result + /// a walker that collects all ranges of syntax elements that contain the given position + [] + type private RangeCollectorWalker(pos: Position) = + inherit SyntaxCollectorBase() + let ranges = ResizeArray() + + let addIfInside (m: Range) = + if (Range.rangeContainsPos m pos) then + ranges.Add m + + override _.WalkSynModuleOrNamespace m = addIfInside m.Range + override _.WalkAttribute a = addIfInside a.Range + override _.WalkTypeConstraint c = addIfInside c.Range + override _.WalkPat p = addIfInside p.Range + + override _.WalkBinding(SynBinding(range = r; returnInfo = ri)) = + addIfInside r + ri |> Option.iter (fun (SynBindingReturnInfo(range = r')) -> addIfInside r') + + override _.WalkInterfaceImpl(SynInterfaceImpl(range = range)) = addIfInside range + override _.WalkType t = addIfInside t.Range + override _.WalkClause c = addIfInside c.Range + + override _.WalkInterpolatedStringPart i = + match i with + | SynInterpolatedStringPart.FillExpr(qualifiers = Some ident) -> addIfInside ident.idRange + | SynInterpolatedStringPart.String(s, r) -> addIfInside r + | _ -> () + + override _.WalkExpr e = addIfInside e.Range + + override _.WalkMeasure m = + match m with + | SynMeasure.Product(range = r) + | SynMeasure.Divide(range = r) + | SynMeasure.Named(range = r) + | SynMeasure.Seq(range = r) + | SynMeasure.Power(range = r) + | SynMeasure.Var(range = r) + | SynMeasure.Paren(range = r) -> addIfInside r + | SynMeasure.One + | SynMeasure.Anon _ -> () + + override _.WalkSimplePat p = addIfInside p.Range + override _.WalkField(SynField(range = r)) = addIfInside r + override _.WalkValSig(SynValSig(range = r)) = addIfInside r + override _.WalkMemberSig m = addIfInside m.Range + override _.WalkMember m = addIfInside m.Range + override _.WalkEnumCase e = addIfInside e.Range + override _.WalkUnionCase u = addIfInside u.Range + override _.WalkTypeDefnSimple s = addIfInside s.Range + override _.WalkComponentInfo c = addIfInside c.Range + override _.WalkTypeDefnRepr t = addIfInside t.Range + override _.WalkTypeDefnSigRepr t = addIfInside t.Range + override _.WalkTypeDefn t = addIfInside t.Range + override _.WalkSynModuleDecl s = addIfInside s.Range + + member _.Ranges = ranges + + let getRangesAtPosition input (r: Position) : Range list = + let walker = new RangeCollectorWalker(r) + walkAst walker input + walker.Ranges |> Seq.toList module Completion = + open FSharp.Compiler.Text + open FSharp.Compiler.Syntax [] type Context = diff --git a/src/FsAutoComplete.Core/UntypedAstUtils.fsi b/src/FsAutoComplete.Core/UntypedAstUtils.fsi index 180da429d..d99122114 100644 --- a/src/FsAutoComplete.Core/UntypedAstUtils.fsi +++ b/src/FsAutoComplete.Core/UntypedAstUtils.fsi @@ -1,36 +1,81 @@ -/// Code from VisualFSharpPowerTools project: https://github.com/fsprojects/VisualFSharpPowerTools/blob/master/src/FSharp.Editing/Common/UntypedAstUtils.fs -module FsAutoComplete.UntypedAstUtils - -open FSharp.Compiler.Syntax -open System.Collections.Generic -open FSharp.Compiler -open FSharp.Compiler.Text -open FSharp.Control.Reactive.Observable - -type Range with - - member inline IsEmpty: bool - -type internal ShortIdent = string -type internal Idents = ShortIdent[] -val internal longIdentToArray: longIdent: LongIdent -> Idents -/// An recursive pattern that collect all sequential expressions to avoid StackOverflowException -val (|Sequentials|_|): (SynExpr -> SynExpr list option) -val (|ConstructorPats|): (SynArgPats -> SynPat list) -/// matches if the range contains the position -val (|ContainsPos|_|): pos: pos -> range: range -> unit option -/// Active pattern that matches an ident on a given name by the ident's `idText` -val (|Ident|_|): ofName: string -> (SynExpr -> unit option) -/// matches if the range contains the position -val (|IdentContainsPos|_|): pos: pos -> ident: Ident -> unit option -/// A pattern that collects all attributes from a `SynAttributes` into a single flat list -val (|AllAttrs|): attrs: SynAttributes -> SynAttribute list -/// A pattern that collects all patterns from a `SynSimplePats` into a single flat list -val (|AllSimplePats|): pats: SynSimplePats -> SynSimplePat list -/// Gives all ranges for current position -val internal getRangesAtPosition: input: ParsedInput -> r: Position -> Range list +namespace FSharp.Compiler + +module Syntax = + open FSharp.Compiler.Syntax + + type SyntaxCollectorBase = + new: unit -> SyntaxCollectorBase + abstract WalkSynModuleOrNamespace: SynModuleOrNamespace -> unit + abstract WalkAttribute: SynAttribute -> unit + abstract WalkSynModuleDecl: SynModuleDecl -> unit + abstract WalkExpr: SynExpr -> unit + abstract WalkTypar: SynTypar -> unit + abstract WalkTyparDecl: SynTyparDecl -> unit + abstract WalkTypeConstraint: SynTypeConstraint -> unit + abstract WalkType: SynType -> unit + abstract WalkMemberSig: SynMemberSig -> unit + abstract WalkPat: SynPat -> unit + abstract WalkValTyparDecls: SynValTyparDecls -> unit + abstract WalkBinding: SynBinding -> unit + abstract WalkSimplePat: SynSimplePat -> unit + abstract WalkInterfaceImpl: SynInterfaceImpl -> unit + abstract WalkClause: SynMatchClause -> unit + abstract WalkInterpolatedStringPart: SynInterpolatedStringPart -> unit + abstract WalkMeasure: SynMeasure -> unit + abstract WalkComponentInfo: SynComponentInfo -> unit + abstract WalkTypeDefnSigRepr: SynTypeDefnSigRepr -> unit + abstract WalkUnionCaseType: SynUnionCaseKind -> unit + abstract WalkEnumCase: SynEnumCase -> unit + abstract WalkField: SynField -> unit + abstract WalkTypeDefnSimple: SynTypeDefnSimpleRepr -> unit + abstract WalkValSig: SynValSig -> unit + abstract WalkMember: SynMemberDefn -> unit + abstract WalkUnionCase: SynUnionCase -> unit + abstract WalkTypeDefnRepr: SynTypeDefnRepr -> unit + abstract WalkTypeDefn: SynTypeDefn -> unit + + val walkAst: walker: SyntaxCollectorBase -> input: ParsedInput -> unit + + /// An recursive pattern that collect all sequential expressions to avoid StackOverflowException + val (|Sequentials|_|): (SynExpr -> SynExpr list option) + val (|ConstructorPats|): (SynArgPats -> SynPat list) + /// A pattern that collects all attributes from a `SynAttributes` into a single flat list + val (|AllAttrs|): attrs: SynAttributes -> SynAttribute list + /// A pattern that collects all patterns from a `SynSimplePats` into a single flat list + val (|AllSimplePats|): pats: SynSimplePats -> SynSimplePat list + +namespace FsAutoComplete + +module UntypedAstUtils = + + open FSharp.Compiler.Syntax + open FSharp.Compiler.Text + + type Range with + + member inline IsEmpty: bool + + type internal ShortIdent = string + type internal Idents = ShortIdent[] + val internal longIdentToArray: longIdent: LongIdent -> Idents + + /// matches if the range contains the position + val (|ContainsPos|_|): pos: pos -> range: range -> unit option + /// Active pattern that matches an ident on a given name by the ident's `idText` + val (|Ident|_|): ofName: string -> (SynExpr -> unit option) + /// matches if the range contains the position + val (|IdentContainsPos|_|): pos: pos -> ident: Ident -> unit option + +module FoldingRange = + open FSharp.Compiler.Syntax + open FSharp.Compiler.Text + + val getRangesAtPosition: input: ParsedInput -> r: Position -> Range list module Completion = + open FSharp.Compiler.Syntax + open FSharp.Compiler.Text + [] type Context = | StringLiteral