From 31118a444b85fd1eeff670bc831382c9f825df49 Mon Sep 17 00:00:00 2001 From: dsyme Date: Thu, 24 Nov 2016 18:32:33 +0000 Subject: [PATCH] fixes for type providers --- src/fsharp/CompileOps.fs | 3 +- src/fsharp/FSharp.Core/reflect.fs | 22 +- tests/fsharp/core/quotes/test.fsx | 258 ++++++++++++++++++ tests/fsharp/core/reflect/test2.fs | 5 +- tests/fsharp/tests.fs | 12 +- .../src/FSharp.Editor/ColorizationService.fs | 12 +- .../src/FSharp.Editor/CompletionProvider.fs | 7 +- .../DocumentDiagnosticAnalyzer.fs | 5 - .../FSharp.Editor/GoToDefinitionService.fs | 5 - 9 files changed, 294 insertions(+), 35 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 91dc03a648..f845dd62b2 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -3998,7 +3998,8 @@ type TcImports(tcConfigP:TcConfigProvider, initialResolutions:TcAssemblyResoluti // dispatch via a thunk which gets set to a non-resource-capturing // failing function when the object is disposed. let systemRuntimeContainsType = - let systemRuntimeContainsTypeRef = ref tcImports.SystemRuntimeContainsType + // NOTE: do not touch this + let systemRuntimeContainsTypeRef = ref (fun typeName -> tcImports.SystemRuntimeContainsType(typeName)) tcImports.AttachDisposeAction(fun () -> systemRuntimeContainsTypeRef := (fun _ -> raise (System.ObjectDisposedException("The type provider has been disposed")))) fun arg -> systemRuntimeContainsTypeRef.Value arg diff --git a/src/fsharp/FSharp.Core/reflect.fs b/src/fsharp/FSharp.Core/reflect.fs index e349494b16..3b4064d129 100644 --- a/src/fsharp/FSharp.Core/reflect.fs +++ b/src/fsharp/FSharp.Core/reflect.fs @@ -367,15 +367,29 @@ module internal Impl = let tupleNames = [| "System.Tuple`1"; "System.Tuple`2"; "System.Tuple`3"; "System.Tuple`4"; "System.Tuple`5"; "System.Tuple`6"; - "System.Tuple`7"; "System.Tuple`8"; "System.Tuple"; + "System.Tuple`7"; "System.Tuple`8"; "System.Tuple" "System.ValueTuple`1"; "System.ValueTuple`2"; "System.ValueTuple`3"; "System.ValueTuple`4"; "System.ValueTuple`5"; "System.ValueTuple`6"; "System.ValueTuple`7"; "System.ValueTuple`8"; "System.ValueTuple" |] + let simpleTupleNames = [| + "Tuple`1"; "Tuple`2"; "Tuple`3"; + "Tuple`4"; "Tuple`5"; "Tuple`6"; + "Tuple`7"; "Tuple`8"; + "ValueTuple`1"; "ValueTuple`2"; "ValueTuple`3"; + "ValueTuple`4"; "ValueTuple`5"; "ValueTuple`6"; + "ValueTuple`7"; "ValueTuple`8"; |] + let isTupleType (typ:Type) = - // Simple Name Match on typ - if typ.IsEnum || typ.IsArray || typ.IsPointer then false - else tupleNames |> Seq.exists typ.FullName.StartsWith + // We need to be careful that we only rely typ.IsGenericType, typ.Namespace and typ.Name here. + // + // Historically the FSharp.Core reflection utilities get used on implementations of + // System.Type that don't have functionality such as .IsEnum and .FullName fully implemented. + // This happens particularly over TypeBuilderInstantiation types in the ProvideTypes implementation of System.TYpe + // used in F# type providers. + typ.IsGenericType && + typ.Namespace = "System" && + simpleTupleNames |> Seq.exists typ.Name.StartsWith let maxTuple = 8 // Which field holds the nested tuple? diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 556d3ec9fb..5f589f5735 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -2708,6 +2708,264 @@ module PartialApplicationLeadToInvalidCodeWhenOptimized = f () + +/// TEST F# REFLECTION OVER THE IMPLEMENTATION OF SYMBOL TYPES FROM THE F# TYPE PROVIDER STARTER PACK +/// +module ReflectionOverTypeInstantiations = + + open System.Collections.Generic + + let notRequired opname item = + let msg = sprintf "The operation '%s' on item '%s' should not be called on provided type, member or parameter" opname item + System.Diagnostics.Debug.Assert (false, msg) + raise (System.NotSupportedException msg) + + /// DO NOT ADJUST THIS TYPE - it is the implementation of symbol types from the F# type provider starer pack. + /// This code gets included in all F# type provider implementations. We expect F# reflection to be in a good, + /// known state over these types. + /// + /// + /// Represents the type constructor in a provided symbol type. + [] + type ProvidedSymbolKind = + | SDArray + | Array of int + | Pointer + | ByRef + | Generic of System.Type + | FSharpTypeAbbreviation of (System.Reflection.Assembly * string * string[]) + + + /// DO NOT ADJUST THIS TYPE - it is the implementation of symbol types from the F# type provider starer pack. + /// This code gets included in all F# type provider implementations. We expect F# reflection to be in a good, + /// known state over these types. + /// + /// Represents an array or other symbolic type involving a provided type as the argument. + /// See the type provider spec for the methods that must be implemented. + /// Note that the type provider specification does not require us to implement pointer-equality for provided types. + type ProvidedSymbolType(kind: ProvidedSymbolKind, args: Type list, convToTgt: Type -> Type) = + inherit Type() + + let rec isEquivalentTo (thisTy: Type) (otherTy: Type) = + match thisTy, otherTy with + | (:? ProvidedSymbolType as thisTy), (:? ProvidedSymbolType as thatTy) -> (thisTy.Kind,thisTy.Args) = (thatTy.Kind, thatTy.Args) + | (:? ProvidedSymbolType as thisTy), otherTy | otherTy, (:? ProvidedSymbolType as thisTy) -> + match thisTy.Kind, thisTy.Args with + | ProvidedSymbolKind.SDArray, [ty] | ProvidedSymbolKind.Array _, [ty] when otherTy.IsArray-> ty.Equals(otherTy.GetElementType()) + | ProvidedSymbolKind.ByRef, [ty] when otherTy.IsByRef -> ty.Equals(otherTy.GetElementType()) + | ProvidedSymbolKind.Pointer, [ty] when otherTy.IsPointer -> ty.Equals(otherTy.GetElementType()) + | ProvidedSymbolKind.Generic baseTy, args -> otherTy.IsGenericType && isEquivalentTo baseTy (otherTy.GetGenericTypeDefinition()) && Seq.forall2 isEquivalentTo args (otherTy.GetGenericArguments()) + | _ -> false + | a, b -> a.Equals b + + let nameText() = + match kind,args with + | ProvidedSymbolKind.SDArray,[arg] -> arg.Name + "[]" + | ProvidedSymbolKind.Array _,[arg] -> arg.Name + "[*]" + | ProvidedSymbolKind.Pointer,[arg] -> arg.Name + "*" + | ProvidedSymbolKind.ByRef,[arg] -> arg.Name + "&" + | ProvidedSymbolKind.Generic gty, args -> gty.Name + (sprintf "%A" args) + | ProvidedSymbolKind.FSharpTypeAbbreviation (_,_,path),_ -> path.[path.Length-1] + | _ -> failwith "unreachable" + + /// Substitute types for type variables. + static member convType (parameters: Type list) (ty:Type) = + if ty = null then null + elif ty.IsGenericType then + let args = Array.map (ProvidedSymbolType.convType parameters) (ty.GetGenericArguments()) + ty.GetGenericTypeDefinition().MakeGenericType(args) + elif ty.HasElementType then + let ety = ProvidedSymbolType.convType parameters (ty.GetElementType()) + if ty.IsArray then + let rank = ty.GetArrayRank() + if rank = 1 then ety.MakeArrayType() + else ety.MakeArrayType(rank) + elif ty.IsPointer then ety.MakePointerType() + elif ty.IsByRef then ety.MakeByRefType() + else ty + elif ty.IsGenericParameter then + if ty.GenericParameterPosition <= parameters.Length - 1 then + parameters.[ty.GenericParameterPosition] + else + ty + else ty + + override __.FullName = + match kind,args with + | ProvidedSymbolKind.SDArray,[arg] -> arg.FullName + "[]" + | ProvidedSymbolKind.Array _,[arg] -> arg.FullName + "[*]" + | ProvidedSymbolKind.Pointer,[arg] -> arg.FullName + "*" + | ProvidedSymbolKind.ByRef,[arg] -> arg.FullName + "&" + | ProvidedSymbolKind.Generic gty, args -> gty.FullName + "[" + (args |> List.map (fun arg -> arg.ToString()) |> String.concat ",") + "]" + | ProvidedSymbolKind.FSharpTypeAbbreviation (_,nsp,path),args -> String.concat "." (Array.append [| nsp |] path) + (match args with [] -> "" | _ -> args.ToString()) + | _ -> failwith "unreachable" + + /// Although not strictly required by the type provider specification, this is required when doing basic operations like FullName on + /// .NET symbolic types made from this type, e.g. when building Nullable.FullName + override __.DeclaringType = + match kind,args with + | ProvidedSymbolKind.SDArray,[arg] -> arg + | ProvidedSymbolKind.Array _,[arg] -> arg + | ProvidedSymbolKind.Pointer,[arg] -> arg + | ProvidedSymbolKind.ByRef,[arg] -> arg + | ProvidedSymbolKind.Generic gty,_ -> gty + | ProvidedSymbolKind.FSharpTypeAbbreviation _,_ -> null + | _ -> failwith "unreachable" + + override __.IsAssignableFrom(otherTy) = + match kind with + | Generic gtd -> + if otherTy.IsGenericType then + let otherGtd = otherTy.GetGenericTypeDefinition() + let otherArgs = otherTy.GetGenericArguments() + let yes = gtd.Equals(otherGtd) && Seq.forall2 isEquivalentTo args otherArgs + yes + else + base.IsAssignableFrom(otherTy) + | _ -> base.IsAssignableFrom(otherTy) + + override __.Name = nameText() + + override __.BaseType = + match kind with + | ProvidedSymbolKind.SDArray -> convToTgt typeof + | ProvidedSymbolKind.Array _ -> convToTgt typeof + | ProvidedSymbolKind.Pointer -> convToTgt typeof + | ProvidedSymbolKind.ByRef -> convToTgt typeof + | ProvidedSymbolKind.Generic gty -> + if gty.BaseType = null then null else + ProvidedSymbolType.convType args gty.BaseType + | ProvidedSymbolKind.FSharpTypeAbbreviation _ -> convToTgt typeof + + override __.GetArrayRank() = (match kind with ProvidedSymbolKind.Array n -> n | ProvidedSymbolKind.SDArray -> 1 | _ -> invalidOp "non-array type") + override __.IsValueTypeImpl() = (match kind with ProvidedSymbolKind.Generic gtd -> gtd.IsValueType | _ -> false) + override __.IsArrayImpl() = (match kind with ProvidedSymbolKind.Array _ | ProvidedSymbolKind.SDArray -> true | _ -> false) + override __.IsByRefImpl() = (match kind with ProvidedSymbolKind.ByRef _ -> true | _ -> false) + override __.IsPointerImpl() = (match kind with ProvidedSymbolKind.Pointer _ -> true | _ -> false) + override __.IsPrimitiveImpl() = false + override __.IsGenericType = (match kind with ProvidedSymbolKind.Generic _ -> true | _ -> false) + override __.GetGenericArguments() = (match kind with ProvidedSymbolKind.Generic _ -> args |> List.toArray | _ -> invalidOp "non-generic type") + override __.GetGenericTypeDefinition() = (match kind with ProvidedSymbolKind.Generic e -> e | _ -> invalidOp "non-generic type") + override __.IsCOMObjectImpl() = false + override __.HasElementTypeImpl() = (match kind with ProvidedSymbolKind.Generic _ -> false | _ -> true) + override __.GetElementType() = (match kind,args with (ProvidedSymbolKind.Array _ | ProvidedSymbolKind.SDArray | ProvidedSymbolKind.ByRef | ProvidedSymbolKind.Pointer),[e] -> e | _ -> invalidOp "not an array, pointer or byref type") + override this.ToString() = this.FullName + + override __.Assembly = + match kind with + | ProvidedSymbolKind.FSharpTypeAbbreviation (assembly,_nsp,_path) -> assembly + | ProvidedSymbolKind.Generic gty -> gty.Assembly + | _ -> notRequired "Assembly" (nameText()) + + override __.Namespace = + match kind with + | ProvidedSymbolKind.FSharpTypeAbbreviation (_assembly,nsp,_path) -> nsp + | _ -> notRequired "Namespace" (nameText()) + + override __.GetHashCode() = + match kind,args with + | ProvidedSymbolKind.SDArray,[arg] -> 10 + hash arg + | ProvidedSymbolKind.Array _,[arg] -> 163 + hash arg + | ProvidedSymbolKind.Pointer,[arg] -> 283 + hash arg + | ProvidedSymbolKind.ByRef,[arg] -> 43904 + hash arg + | ProvidedSymbolKind.Generic gty,_ -> 9797 + hash gty + List.sumBy hash args + | ProvidedSymbolKind.FSharpTypeAbbreviation _,_ -> 3092 + | _ -> failwith "unreachable" + + override __.Equals(other: obj) = + match other with + | :? ProvidedSymbolType as otherTy -> (kind, args) = (otherTy.Kind, otherTy.Args) + | _ -> false + + member __.Kind = kind + member __.Args = args + + member __.IsFSharpTypeAbbreviation = match kind with FSharpTypeAbbreviation _ -> true | _ -> false + // For example, int + member __.IsFSharpUnitAnnotated = match kind with ProvidedSymbolKind.Generic gtd -> not gtd.IsGenericTypeDefinition | _ -> false + + override __.Module : Module = notRequired "Module" (nameText()) + override __.GetConstructors _bindingAttr = notRequired "GetConstructors" (nameText()) + override __.GetMethodImpl(_name, _bindingAttr, _binderBinder, _callConvention, _types, _modifiers) = + match kind with + | Generic gtd -> + let ty = gtd.GetGenericTypeDefinition().MakeGenericType(Array.ofList args) + ty.GetMethod(_name, _bindingAttr) + | _ -> notRequired "GetMethodImpl" (nameText()) + override __.GetMembers _bindingAttr = notRequired "GetMembers" (nameText()) + override __.GetMethods _bindingAttr = notRequired "GetMethods" (nameText()) + override __.GetField(_name, _bindingAttr) = notRequired "GetField" (nameText()) + override __.GetFields _bindingAttr = notRequired "GetFields" (nameText()) + override __.GetInterface(_name, _ignoreCase) = notRequired "GetInterface" (nameText()) + override __.GetInterfaces() = notRequired "GetInterfaces" (nameText()) + override __.GetEvent(_name, _bindingAttr) = notRequired "GetEvent" (nameText()) + override __.GetEvents _bindingAttr = notRequired "GetEvents" (nameText()) + override __.GetProperties _bindingAttr = notRequired "GetProperties" (nameText()) + override __.GetPropertyImpl(_name, _bindingAttr, _binder, _returnType, _types, _modifiers) = notRequired "GetPropertyImpl" (nameText()) + override __.GetNestedTypes _bindingAttr = notRequired "GetNestedTypes" (nameText()) + override __.GetNestedType(_name, _bindingAttr) = notRequired "GetNestedType" (nameText()) + override __.GetAttributeFlagsImpl() = notRequired "GetAttributeFlagsImpl" (nameText()) + override this.UnderlyingSystemType = + match kind with + | ProvidedSymbolKind.SDArray + | ProvidedSymbolKind.Array _ + | ProvidedSymbolKind.Pointer + | ProvidedSymbolKind.FSharpTypeAbbreviation _ + | ProvidedSymbolKind.ByRef -> upcast this + | ProvidedSymbolKind.Generic gty -> gty.UnderlyingSystemType + #if FX_NO_CUSTOMATTRIBUTEDATA + #else + override __.GetCustomAttributesData() = ([| |] :> IList<_>) + #endif + override __.MemberType = notRequired "MemberType" (nameText()) + override __.GetMember(_name,_mt,_bindingAttr) = notRequired "GetMember" (nameText()) + override __.GUID = notRequired "GUID" (nameText()) + override __.InvokeMember(_name, _invokeAttr, _binder, _target, _args, _modifiers, _culture, _namedParameters) = notRequired "InvokeMember" (nameText()) + override __.AssemblyQualifiedName = notRequired "AssemblyQualifiedName" (nameText()) + override __.GetConstructorImpl(_bindingAttr, _binder, _callConvention, _types, _modifiers) = notRequired "GetConstructorImpl" (nameText()) + override __.GetCustomAttributes(_inherit) = [| |] + override __.GetCustomAttributes(_attributeType, _inherit) = [| |] + override __.IsDefined(_attributeType, _inherit) = false + // FSharp.Data addition: this was added to support arrays of arrays + override this.MakeArrayType() = ProvidedSymbolType(ProvidedSymbolKind.SDArray, [this], convToTgt) :> Type + override this.MakeArrayType arg = ProvidedSymbolType(ProvidedSymbolKind.Array arg, [this], convToTgt) :> Type + + + + /// DO NOT ADJUST THIS TYPE - it is the implementation of symbol types from the F# type provider starer pack. + /// This code gets included in all F# type provider implementations. We expect F# reflection to be in a good, + /// known state over these types. + type ProvidedTypeBuilder() = + static member MakeGenericType(genericTypeDefinition, genericArguments) = ProvidedSymbolType(Generic genericTypeDefinition, genericArguments, id) :> Type + + + /// TEST BEGINS HERE + // + let checkType nm (ty:System.Type) isTup = + // Calls to basic properties are in a known state + check (nm + "-falihksec0 - expect IsArray to give accurate results on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.IsArray |> Some with e -> None) (Some false) + check (nm + "-falihksec1 - expect IsPointer to give accurate results on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.IsPointer |> Some with e -> None) (Some false) + check (nm + "-falihksec2 - expect IsAbstract to give accurate results on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.IsAbstract |> Some with e -> None) (Some false) + check (nm + "-falihksec3 - expect IsClass to give accurate results on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.IsClass |> Some with e -> None) (Some true) + check (nm + "-falihksec4 - expect IsValueType to give accurate results on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.IsValueType |> Some with e -> None) (Some false) + check (nm + "-falihksec5 - expect IsTuple to give accurate results on typical F# type provider implementation of TypeBuilderInstantiation") (try Reflection.FSharpType.IsTuple(ty) |> Some with _ -> None) (Some isTup) + + check (nm + "-falihksec3a - currently expect IsEnum to throw on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.IsEnum |> ignore; 100 with e -> 200) 200 + check (nm + "-falihksec4a - currently expect FullName to throw on typical F# type provider implementation of TypeBuilderInstantiation") (try ty.FullName |> ignore; 100 with e -> 200) 200 + check (nm + "-falihksec5a - currently expect IsFunction to throw on typical F# type provider implementation of TypeBuilderInstantiation") (try Reflection.FSharpType.IsFunction(ty) |> ignore; 100 with _ -> 200) 200 + check (nm + "-falihksec6a - currently expect IsUnion to throw on typical F# type provider implementation of TypeBuilderInstantiation") (try Reflection.FSharpType.IsUnion(ty) |> ignore; 100 with :? System.NotSupportedException -> 200) 200 + check (nm + "-falihksec7a - currently expect IsRecord to throw on typical F# type provider implementation of TypeBuilderInstantiation") (try Reflection.FSharpType.IsRecord (ty) |> ignore; 100 with :? System.NotSupportedException -> 200) 200 + check (nm + "-falihksec8a - currently expect IsModule to throw on typical F# type provider implementation of TypeBuilderInstantiation") (try Reflection.FSharpType.IsModule (ty) |> ignore; 100 with :? System.NotSupportedException -> 200) 200 + + // This makes a TypeBuilderInstantiation type, because a real type has been instantiated with a non-real type + let t0 = ProvidedTypeBuilder.MakeGenericType(typedefof>, [ typeof ]) + let t1 = typedefof>.MakeGenericType(t0) + let t2 = typedefof.MakeGenericType(t0, t0) + + checkType "test cvweler8" t1 false + checkType "test cvweler9" t2 true + + #if !FX_RESHAPED_REFLECTION module TestAssemblyAttributes = let attributes = System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(false) diff --git a/tests/fsharp/core/reflect/test2.fs b/tests/fsharp/core/reflect/test2.fs index 103bdd17cd..2be9a38383 100644 --- a/tests/fsharp/core/reflect/test2.fs +++ b/tests/fsharp/core/reflect/test2.fs @@ -253,7 +253,7 @@ module TwoCasedUnionWithNullAsTrueValueAnnotation = with _ -> false test "TwoCasedUnionWithNullAsTrueValueAnnotation" result -module TEst = begin +module TEst = type token = | X @@ -292,9 +292,6 @@ module TEst = begin let _ = printany (1,true,2.4,"a tuple",("nested",(fun () -> ()),[2;3],rrv)) let _ = printany printany (* =) *) -end - - let _ = if !failures then (stdout.WriteLine "Test Failed"; exit 1) else (stdout.WriteLine "Test Passed"; diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index f64606d503..180ab72b64 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -641,6 +641,12 @@ module CoreTests = peverify cfg "test.exe" + begin + use testOkFile = fileguard cfg "test.ok" + exec cfg ("." ++ "test.exe") "" + testOkFile.CheckExists() + end + fsc cfg "%s -o:test-with-debug-data.exe --quotations-debug+ -r cslib.dll -g" cfg.fsc_flags ["test.fsx"] peverify cfg "test-with-debug-data.exe" @@ -657,12 +663,6 @@ module CoreTests = testOkFile.CheckExists() end - begin - use testOkFile = fileguard cfg "test.ok" - exec cfg ("." ++ "test.exe") "" - testOkFile.CheckExists() - end - begin use testOkFile = fileguard cfg "test.ok" exec cfg ("." ++ "test-with-debug-data.exe") "" diff --git a/vsintegration/src/FSharp.Editor/ColorizationService.fs b/vsintegration/src/FSharp.Editor/ColorizationService.fs index 669c1b7b49..931ec8023b 100644 --- a/vsintegration/src/FSharp.Editor/ColorizationService.fs +++ b/vsintegration/src/FSharp.Editor/ColorizationService.fs @@ -15,6 +15,7 @@ open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Classification open Microsoft.CodeAnalysis.Editor open Microsoft.CodeAnalysis.Editor.Implementation.Classification +open Microsoft.CodeAnalysis.Editor.Implementation.BlockCommentEditing open Microsoft.CodeAnalysis.Editor.Shared.Utilities open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.Text @@ -22,6 +23,8 @@ open Microsoft.CodeAnalysis.Text open Microsoft.VisualStudio.FSharp.LanguageService open Microsoft.VisualStudio.Text open Microsoft.VisualStudio.Text.Tagging +open Microsoft.VisualStudio.Text.Operations +open Microsoft.VisualStudio.Utilities open Microsoft.FSharp.Compiler.SourceCodeServices @@ -55,6 +58,7 @@ type private SourceTextData(approxLines: int) = i <- i + 1 + [, FSharpCommonConstants.FSharpLanguageName)>] type internal FSharpColorizationService() = @@ -193,11 +197,6 @@ type internal FSharpColorizationService() = match FSharpLanguageService.GetOptions(document.Project.Id) with | Some(options) -> let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask - // REVIEW: ParseFileInProject and CheckFileInProject can cause FSharp.Compiler.Service to become unavailable (i.e. not responding to requests) for - // an arbitrarily long time while they process all files prior to this one in the project (plus dependent projects if we enable - // cross-project checking in multi-project solutions). FCS will not respond to other - // requests unless this task is cancelled. We need to check that this task is cancelled in a timely way by the - // Roslyn UI machinery. let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(document.Name, sourceText.ToString(), options) let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask let! checkResultsAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, document.FilePath, textVersion.GetHashCode(), textSpan.ToString(), options) @@ -214,3 +213,6 @@ type internal FSharpColorizationService() = // Do not perform classification if we don't have project options (#defines matter) member this.AdjustStaleClassification(_: SourceText, classifiedSpan: ClassifiedSpan) : ClassifiedSpan = classifiedSpan + + + diff --git a/vsintegration/src/FSharp.Editor/CompletionProvider.fs b/vsintegration/src/FSharp.Editor/CompletionProvider.fs index 8e8c5e1ef2..d83b2d0883 100644 --- a/vsintegration/src/FSharp.Editor/CompletionProvider.fs +++ b/vsintegration/src/FSharp.Editor/CompletionProvider.fs @@ -77,11 +77,6 @@ type internal FSharpCompletionProvider(workspace: Workspace, serviceProvider: SV | _ -> true // anything else is a valid classification type static member ProvideCompletionsAsyncAux(sourceText: SourceText, caretPosition: int, options: FSharpProjectOptions, filePath: string, textVersionHash: int) = async { - // REVIEW: ParseFileInProject and CheckFileInProject can cause FSharp.Compiler.Service to become unavailable (i.e. not responding to requests) for - // an arbitrarily long time while they process all files prior to this one in the project (plus dependent projects - // if we enable cross-project checking in multi-project solutions). FCS will not respond to other - // requests unless this task is cancelled. We need to check that this task is cancelled in a timely way by the - // Roslyn UI machinery. let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(filePath, sourceText.ToString(), options) let! checkFileAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) let checkFileResults = @@ -100,6 +95,8 @@ type internal FSharpCompletionProvider(workspace: Workspace, serviceProvider: SV let results = List() for declarationItem in declarations.Items do + // FSROSLYNTODO: This doesn't yet reflect pulbic/private/internal into the glyph + // FSROSLYNTODO: We should really use FSharpSymbol information here. But GetDeclarationListInfo doesn't provide it, and switch to GetDeclarationListSymbols is a bit large at the moment let glyph = match declarationItem.GlyphMajor with | GlyphMajor.Class -> Glyph.ClassPublic diff --git a/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs index dbbceb66a8..6d9bd22c2d 100644 --- a/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs @@ -25,11 +25,6 @@ type internal FSharpDocumentDiagnosticAnalyzer() = inherit DocumentDiagnosticAnalyzer() static member GetDiagnostics(filePath: string, sourceText: SourceText, textVersionHash: int, options: FSharpProjectOptions, addSemanticErrors: bool) = async { - // REVIEW: ParseFileInProject and CheckFileInProject can cause FSharp.Compiler.Service to become unavailable (i.e. not responding to requests) for - // an arbitrarily long time while they process all files prior to this one in the project (plus dependent projects - // if we enable cross-project checking in multi-project solutions). FCS will not respond to other - // requests unless this task is cancelled. We need to check that this task is cancelled in a timely way by the - // Roslyn UI machinery. let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(filePath, sourceText.ToString(), options) let! errors = async { if addSemanticErrors then diff --git a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs index 2e02a54c6b..ec2206e8dc 100644 --- a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs @@ -69,11 +69,6 @@ type internal FSharpGoToDefinitionService [] ([ let qualifiers = if isQuoted then [islandIdentifier] else islandIdentifier.Split '.' |> Array.toList - // REVIEW: ParseFileInProject and CheckFileInProject can cause FSharp.Compiler.Service to become unavailable (i.e. not responding to requests) for - // an arbitrarily long time while they process all files prior to this one in the project (plus dependent projects - // if we enable cross-project checking in multi-project solutions). FCS will not respond to other - // requests unless this task is cancelled. We need to check that this task is cancelled in a timely way by the - // Roslyn UI machinery. let! parseResults = FSharpLanguageService.Checker.ParseFileInProject(filePath, sourceText.ToString(), options) let! checkFileAnswer = FSharpLanguageService.Checker.CheckFileInProject(parseResults, filePath, textVersionHash, sourceText.ToString(), options) let checkFileResults =