提交 fbf7ea0c 编写于 作者: J Jared Hester 提交者: Kevin Ransom (msft)

Editor refactor (#2780)

* split out language service into dedicated dir

* dedicated extensions module

* trim pervasive

* rename constants

* symbols module

* typedastutils module

* FSharpChecker extensions

* rename roslyn helpers

* editor rename cleanup

* fix test renaming
上级 8cfd8878
......@@ -5,7 +5,7 @@ open Microsoft.CodeAnalysis.Host.Mef
open System.Composition
[<Shared>]
[<ExportLanguageService(typeof<ICommentUncommentService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<ICommentUncommentService>, FSharpConstants.FSharpLanguageName)>]
type CommentUncommentService() =
interface ICommentUncommentService with
member this.SingleLineCommentString = "//"
......
......@@ -14,7 +14,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.FSharp.Compiler.SourceCodeServices
[<ExportLanguageService(typeof<IEditorClassificationService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<IEditorClassificationService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpColorizationService
[<ImportingConstructor>]
(
......@@ -30,8 +30,8 @@ type internal FSharpColorizationService
async {
let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document)
let! sourceText = document.GetTextAsync(cancellationToken)
result.AddRange(CommonHelpers.getColorizationData(document.Id, sourceText, textSpan, Some(document.FilePath), defines, cancellationToken))
} |> CommonRoslynHelpers.StartAsyncUnitAsTask cancellationToken
result.AddRange(Tokenizer.getColorizationData(document.Id, sourceText, textSpan, Some(document.FilePath), defines, cancellationToken))
} |> RoslynHelpers.StartAsyncUnitAsTask cancellationToken
member this.AddSemanticClassificationsAsync(document: Document, textSpan: TextSpan, result: List<ClassifiedSpan>, cancellationToken: CancellationToken) =
asyncMaybe {
......@@ -39,14 +39,14 @@ type internal FSharpColorizationService
let! sourceText = document.GetTextAsync(cancellationToken)
let! _, _, checkResults = checkerProvider.Checker.ParseAndCheckDocument(document, options, sourceText = sourceText, allowStaleResults = false)
// it's crucial to not return duplicated or overlapping `ClassifiedSpan`s because Find Usages service crashes.
let targetRange = CommonRoslynHelpers.TextSpanToFSharpRange(document.FilePath, textSpan, sourceText)
let targetRange = RoslynHelpers.TextSpanToFSharpRange(document.FilePath, textSpan, sourceText)
let colorizationData = checkResults.GetSemanticClassification (Some targetRange) |> Array.distinctBy fst
for (range, classificationType) in colorizationData do
let span = CommonHelpers.fixupSpan(sourceText, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
let span = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
result.Add(ClassifiedSpan(span, FSharpClassificationTypes.getClassificationTypeName(classificationType)))
}
|> Async.Ignore |> CommonRoslynHelpers.StartAsyncUnitAsTask cancellationToken
|> Async.Ignore |> RoslynHelpers.StartAsyncUnitAsTask cancellationToken
// Do not perform classification if we don't have project options (#defines matter)
member this.AdjustStaleClassification(_: SourceText, classifiedSpan: ClassifiedSpan) : ClassifiedSpan = classifiedSpan
......
......@@ -11,7 +11,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.CodeFixes
open Microsoft.CodeAnalysis.CodeActions
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "AddNewKeyword"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "AddNewKeyword"); Shared>]
type internal FSharpAddNewKeywordCodeFixProvider() =
inherit CodeFixProvider()
......@@ -27,7 +27,7 @@ type internal FSharpAddNewKeywordCodeFixProvider() =
async {
let! sourceText = context.Document.GetTextAsync()
return context.Document.WithText(sourceText.WithChanges(TextChange(TextSpan(context.Span.Start, 0), "new ")))
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title), context.Diagnostics |> Seq.filter (fun x -> this.FixableDiagnosticIds.Contains x.Id) |> Seq.toImmutableArray)
} |> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
} |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
......@@ -17,7 +17,7 @@ open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "AddOpen"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "AddOpen"); Shared>]
type internal FSharpAddOpenCodeFixProvider
[<ImportingConstructor>]
(
......@@ -38,7 +38,7 @@ type internal FSharpAddOpenCodeFixProvider
async {
let! sourceText = context.Document.GetTextAsync()
return context.Document.WithText(sourceText.Replace(context.Span, qualifier))
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken))
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken))
let openNamespaceFix (context: CodeFixContext) ctx name ns multipleNames =
let displayText = "open " + ns + if multipleNames then " (" + name + ")" else ""
......@@ -50,7 +50,7 @@ type internal FSharpAddOpenCodeFixProvider
let! sourceText = context.Document.GetTextAsync()
let changedText, _ = OpenDeclarationHelper.insertOpenDeclaration sourceText ctx ns
return context.Document.WithText(changedText)
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
displayText)
let getSuggestions (context: CodeFixContext) (candidates: (Entity * InsertContext) list) : unit =
......@@ -101,7 +101,7 @@ type internal FSharpAddOpenCodeFixProvider
let! symbol =
asyncMaybe {
let! lexerSymbol = CommonHelpers.getSymbolAtPosition(document.Id, sourceText, context.Span.End, document.FilePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, context.Span.End, document.FilePath, defines, Tokenizer.SymbolLookupKind.Greedy)
return! checkResults.GetSymbolUseAtLocation(Line.fromZ linePos.Line, lexerSymbol.Ident.idRange.EndColumn, line.ToString(), lexerSymbol.FullIsland)
} |> liftAsync
......@@ -145,5 +145,5 @@ type internal FSharpAddOpenCodeFixProvider
return entities |> Seq.map createEntity |> Seq.concat |> Seq.toList |> getSuggestions context
}
|> Async.Ignore
|> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
......@@ -24,7 +24,7 @@ type internal InterfaceState =
AppendBracketAt: int option
Tokens: FSharpTokenInfo list }
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "ImplementInterface"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "ImplementInterface"); Shared>]
type internal FSharpImplementInterfaceCodeFixProvider
[<ImportingConstructor>]
(
......@@ -125,7 +125,7 @@ type internal FSharpImplementInterfaceCodeFixProvider
InterfaceStubGenerator.getImplementedMemberSignatures getMemberByLocation displayContext state.InterfaceData
let newSourceText = applyImplementInterface sourceText state displayContext implementedMemberSignatures entity indentSize verboseMode
return context.Document.WithText(newSourceText)
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
context.RegisterCodeFix(codeAction, diagnostics)
......@@ -146,7 +146,7 @@ type internal FSharpImplementInterfaceCodeFixProvider
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(context.Document.FilePath, options.OtherOptions |> Seq.toList)
// Notice that context.Span doesn't return reliable ranges to find tokens at exact positions.
// That's why we tokenize the line and try to find the last successive identifier token
let tokens = CommonHelpers.tokenizeLine(context.Document.Id, sourceText, context.Span.Start, context.Document.FilePath, defines)
let tokens = Tokenizer.tokenizeLine(context.Document.Id, sourceText, context.Span.Start, context.Document.FilePath, defines)
let startLeftColumn = context.Span.Start - textLine.Start
let rec tryFindIdentifierToken acc tokens =
match tokens with
......@@ -169,11 +169,11 @@ type internal FSharpImplementInterfaceCodeFixProvider
| _ ->
Some context.Span.End
let! interfaceState = queryInterfaceState appendBracketAt interfacePos tokens parsedInput
let! symbol = CommonHelpers.getSymbolAtPosition(context.Document.Id, sourceText, fixupPosition, context.Document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(context.Document.Id, sourceText, fixupPosition, context.Document.FilePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let fcsTextLineNumber = textLine.LineNumber + 1
let lineContents = textLine.ToString()
let! options = context.Document.GetOptionsAsync(cancellationToken)
let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpCommonConstants.FSharpLanguageName)
let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpConstants.FSharpLanguageName)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, lineContents, symbol.FullIsland)
let! entity, displayContext =
match symbolUse.Symbol with
......@@ -185,4 +185,4 @@ type internal FSharpImplementInterfaceCodeFixProvider
registerSuggestions (context, checkFileResults, interfaceState, displayContext, entity, tabSize)
}
|> Async.Ignore
|> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
......@@ -13,7 +13,7 @@ open Microsoft.CodeAnalysis.CodeActions
open Microsoft.FSharp.Compiler
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "PrefixUnusedValueWithUnderscore"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "PrefixUnusedValueWithUnderscore"); Shared>]
type internal FSharpPrefixUnusedValueWithUnderscoreCodeFixProvider() =
inherit CodeFixProvider()
let fixableDiagnosticIds = ["FS1182"]
......@@ -25,7 +25,7 @@ type internal FSharpPrefixUnusedValueWithUnderscoreCodeFixProvider() =
async {
let! sourceText = context.Document.GetTextAsync()
return context.Document.WithText(sourceText.WithChanges(textChange))
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
override __.FixableDiagnosticIds = Seq.toImmutableArray fixableDiagnosticIds
......@@ -41,4 +41,4 @@ type internal FSharpPrefixUnusedValueWithUnderscoreCodeFixProvider() =
let diagnostics = context.Diagnostics |> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id) |> Seq.toImmutableArray
context.RegisterCodeFix(createCodeFix(SR.PrefixValueNameWithUnderscore.Value, context, TextChange(TextSpan(context.Span.Start, 0), "_")), diagnostics)
context.RegisterCodeFix(createCodeFix(SR.RenameValueToUnderscore.Value, context, TextChange(context.Span, "_")), diagnostics)
} |> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
} |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
......@@ -7,7 +7,7 @@ open System.Threading.Tasks
open Microsoft.CodeAnalysis.CodeFixes
open Microsoft.CodeAnalysis.CodeActions
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "ProposeUpperCaseLabel"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "ProposeUpperCaseLabel"); Shared>]
type internal FSharpProposeUpperCaseLabelCodeFixProvider
[<ImportingConstructor>]
(
......@@ -27,4 +27,4 @@ type internal FSharpProposeUpperCaseLabelCodeFixProvider
context.RegisterCodeFix(
CodeAction.Create(title, solutionChanger, title),
context.Diagnostics |> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id) |> Seq.toImmutableArray)
} |> Async.Ignore |> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
} |> Async.Ignore |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
......@@ -14,7 +14,7 @@ open Microsoft.CodeAnalysis.CodeActions
open Microsoft.FSharp.Compiler.Range
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "RemoveUnusedOpens"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "RemoveUnusedOpens"); Shared>]
type internal FSharpRemoveUnusedOpensCodeFixProvider
[<ImportingConstructor>]
(
......@@ -44,7 +44,7 @@ type internal FSharpRemoveUnusedOpensCodeFixProvider
return document.WithText(sourceText.WithChanges(changes))
}
|> Async.map (Option.defaultValue context.Document)
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
override __.FixableDiagnosticIds = Seq.toImmutableArray fixableDiagnosticIds
......@@ -53,7 +53,7 @@ type internal FSharpRemoveUnusedOpensCodeFixProvider
async {
let diagnostics = context.Diagnostics |> Seq.filter (fun x -> fixableDiagnosticIds |> List.contains x.Id) |> Seq.toImmutableArray
context.RegisterCodeFix(createCodeFix(SR.RemoveUnusedOpens.Value, context), diagnostics)
} |> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
} |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
override __.GetFixAllProvider() = WellKnownFixAllProviders.BatchFixer
\ No newline at end of file
......@@ -13,7 +13,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.CodeFixes
open Microsoft.CodeAnalysis.CodeActions
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = "ReplaceWithSuggestion"); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = "ReplaceWithSuggestion"); Shared>]
type internal FSharpReplaceWithSuggestionCodeFixProvider() =
inherit CodeFixProvider()
let fixableDiagnosticIds = set ["FS0039"; "FS1129"; "FS0495"]
......@@ -26,7 +26,7 @@ type internal FSharpReplaceWithSuggestionCodeFixProvider() =
async {
let! sourceText = context.Document.GetTextAsync()
return context.Document.WithText(sourceText.WithChanges(textChange))
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
override __.FixableDiagnosticIds = Seq.toImmutableArray fixableDiagnosticIds
......@@ -53,4 +53,4 @@ type internal FSharpReplaceWithSuggestionCodeFixProvider() =
context,
TextChange(context.Span, replacement))
context.RegisterCodeFix(codefix, diagnostics))
} |> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
} |> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
......@@ -13,7 +13,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.CodeFixes
open Microsoft.CodeAnalysis.CodeActions
[<ExportCodeFixProvider(FSharpCommonConstants.FSharpLanguageName, Name = PredefinedCodeFixProviderNames.SimplifyNames); Shared>]
[<ExportCodeFixProvider(FSharpConstants.FSharpLanguageName, Name = PredefinedCodeFixProviderNames.SimplifyNames); Shared>]
type internal FSharpSimplifyNameCodeFixProvider() =
inherit CodeFixProvider()
let fixableDiagnosticId = IDEDiagnosticIds.SimplifyNamesDiagnosticId
......@@ -25,7 +25,7 @@ type internal FSharpSimplifyNameCodeFixProvider() =
async {
let! sourceText = context.Document.GetTextAsync()
return context.Document.WithText(sourceText.WithChanges(textChange))
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)),
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)),
title)
override __.FixableDiagnosticIds = ImmutableArray.Create(fixableDiagnosticId)
......@@ -42,4 +42,4 @@ type internal FSharpSimplifyNameCodeFixProvider() =
createCodeFix(title, context, TextChange(context.Span, "")),
ImmutableArray.Create(diagnostic))
}
|> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
......@@ -73,7 +73,7 @@ type internal FsiCommandFilter(serviceProvider: System.IServiceProvider) =
VSConstants.E_FAIL
[<Export(typeof<IWpfTextViewCreationListener>)>]
[<ContentType(FSharpCommonConstants.FSharpContentTypeName)>]
[<ContentType(FSharpConstants.FSharpContentTypeName)>]
[<TextViewRole(PredefinedTextViewRoles.PrimaryDocument)>]
type internal FsiCommandFilterProvider [<ImportingConstructor>]
([<Import(typeof<SVsServiceProvider>)>] serviceProvider: System.IServiceProvider,
......
......@@ -14,7 +14,7 @@ open Microsoft.CodeAnalysis.Host.Mef
open Microsoft.FSharp.Compiler.Range
[<Shared>]
[<ExportLanguageService(typeof<IHelpContextService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<IHelpContextService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpHelpContextService
[<ImportingConstructor>]
(
......@@ -93,8 +93,8 @@ type internal FSharpHelpContextService
}
interface IHelpContextService with
member this.Language = FSharpCommonConstants.FSharpLanguageLongName
member this.Product = FSharpCommonConstants.FSharpLanguageLongName
member this.Language = FSharpConstants.FSharpLanguageLongName
member this.Product = FSharpConstants.FSharpLanguageLongName
member this.GetHelpTermAsync(document, textSpan, cancellationToken) =
asyncMaybe {
......@@ -103,11 +103,11 @@ type internal FSharpHelpContextService
let! textVersion = document.GetTextVersionAsync(cancellationToken)
let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document)
let textLine = sourceText.Lines.GetLineFromPosition(textSpan.Start)
let tokens = CommonHelpers.getColorizationData(document.Id, sourceText, textLine.Span, Some document.Name, defines, cancellationToken)
let tokens = Tokenizer.getColorizationData(document.Id, sourceText, textLine.Span, Some document.Name, defines, cancellationToken)
return! FSharpHelpContextService.GetHelpTerm(checkerProvider.Checker, sourceText, document.FilePath, options, textSpan, tokens, textVersion.GetHashCode())
}
|> Async.map (Option.defaultValue "")
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
member this.FormatSymbol(_symbol) = Unchecked.defaultof<_>
......@@ -109,7 +109,7 @@ type internal XmlDocCommandFilter
VSConstants.E_FAIL
[<Export(typeof<IWpfTextViewCreationListener>)>]
[<ContentType(FSharpCommonConstants.FSharpContentTypeName)>]
[<ContentType(FSharpConstants.FSharpContentTypeName)>]
[<TextViewRole(PredefinedTextViewRoles.PrimaryDocument)>]
type internal XmlDocCommandFilterProvider
[<ImportingConstructor>]
......
......@@ -8,7 +8,7 @@ open System.Diagnostics
open Microsoft.CodeAnalysis.Classification
[<RequireQualifiedAccess>]
module internal FSharpCommonConstants =
module internal FSharpConstants =
[<Literal>]
/// "871D2A70-12A2-4e42-9440-425DD92A4116"
......
......@@ -9,19 +9,19 @@ open Microsoft.VisualStudio.Utilities
module FSharpStaticTypeDefinitions =
[<Export>]
[<Name(FSharpCommonConstants.FSharpContentTypeName)>]
[<Name(FSharpConstants.FSharpContentTypeName)>]
[<BaseDefinition(ContentTypeNames.RoslynContentType)>]
let FSharpContentTypeDefinition = ContentTypeDefinition()
[<Export>]
[<Name(FSharpCommonConstants.FSharpSignatureHelpContentTypeName)>]
[<Name(FSharpConstants.FSharpSignatureHelpContentTypeName)>]
[<BaseDefinition("sighelp")>]
let FSharpSignatureHelpContentTypeDefinition = ContentTypeDefinition()
[<ExportContentTypeLanguageService(FSharpCommonConstants.FSharpContentTypeName, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportContentTypeLanguageService(FSharpConstants.FSharpContentTypeName, FSharpConstants.FSharpLanguageName)>]
type FSharpContentType [<System.Composition.ImportingConstructor>](contentTypeRegistry : IContentTypeRegistryService) =
member this.contentTypeRegistryService = contentTypeRegistry
interface IContentTypeLanguageService with
member this.GetDefaultContentType() =
this.contentTypeRegistryService.GetContentType(FSharpCommonConstants.FSharpContentTypeName)
this.contentTypeRegistryService.GetContentType(FSharpConstants.FSharpContentTypeName)
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
[<AutoOpen>]
/// Type and Module Extensions
module internal Microsoft.VisualStudio.FSharp.Editor.Extensions
open System
open System.IO
open Microsoft.CodeAnalysis
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.SourceCodeServices
type Path with
static member GetFullPathSafe path =
try Path.GetFullPath path
with _ -> path
static member GetFileNameSafe path =
try Path.GetFileName path
with _ -> path
type System.IServiceProvider with
member x.GetService<'T>() = x.GetService(typeof<'T>) :?> 'T
member x.GetService<'S, 'T>() = x.GetService(typeof<'S>) :?> 'T
type FSharpNavigationDeclarationItem with
member x.RoslynGlyph : Glyph =
match x.Glyph with
| FSharpGlyph.Class
| FSharpGlyph.Typedef
| FSharpGlyph.Type
| FSharpGlyph.Exception ->
match x.Access with
| Some SynAccess.Private -> Glyph.ClassPrivate
| Some SynAccess.Internal -> Glyph.ClassInternal
| _ -> Glyph.ClassPublic
| FSharpGlyph.Constant ->
match x.Access with
| Some SynAccess.Private -> Glyph.ConstantPrivate
| Some SynAccess.Internal -> Glyph.ConstantInternal
| _ -> Glyph.ConstantPublic
| FSharpGlyph.Delegate ->
match x.Access with
| Some SynAccess.Private -> Glyph.DelegatePrivate
| Some SynAccess.Internal -> Glyph.DelegateInternal
| _ -> Glyph.DelegatePublic
| FSharpGlyph.Union
| FSharpGlyph.Enum ->
match x.Access with
| Some SynAccess.Private -> Glyph.EnumPrivate
| Some SynAccess.Internal -> Glyph.EnumInternal
| _ -> Glyph.EnumPublic
| FSharpGlyph.EnumMember
| FSharpGlyph.Variable
| FSharpGlyph.Field ->
match x.Access with
| Some SynAccess.Private -> Glyph.FieldPrivate
| Some SynAccess.Internal -> Glyph.FieldInternal
| _ -> Glyph.FieldPublic
| FSharpGlyph.Event ->
match x.Access with
| Some SynAccess.Private -> Glyph.EventPrivate
| Some SynAccess.Internal -> Glyph.EventInternal
| _ -> Glyph.EventPublic
| FSharpGlyph.Interface ->
match x.Access with
| Some SynAccess.Private -> Glyph.InterfacePrivate
| Some SynAccess.Internal -> Glyph.InterfaceInternal
| _ -> Glyph.InterfacePublic
| FSharpGlyph.Method
| FSharpGlyph.OverridenMethod ->
match x.Access with
| Some SynAccess.Private -> Glyph.MethodPrivate
| Some SynAccess.Internal -> Glyph.MethodInternal
| _ -> Glyph.MethodPublic
| FSharpGlyph.Module ->
match x.Access with
| Some SynAccess.Private -> Glyph.ModulePrivate
| Some SynAccess.Internal -> Glyph.ModuleInternal
| _ -> Glyph.ModulePublic
| FSharpGlyph.NameSpace -> Glyph.Namespace
| FSharpGlyph.Property ->
match x.Access with
| Some SynAccess.Private -> Glyph.PropertyPrivate
| Some SynAccess.Internal -> Glyph.PropertyInternal
| _ -> Glyph.PropertyPublic
| FSharpGlyph.Struct ->
match x.Access with
| Some SynAccess.Private -> Glyph.StructurePrivate
| Some SynAccess.Internal -> Glyph.StructureInternal
| _ -> Glyph.StructurePublic
| FSharpGlyph.ExtensionMethod ->
match x.Access with
| Some SynAccess.Private -> Glyph.ExtensionMethodPrivate
| Some SynAccess.Internal -> Glyph.ExtensionMethodInternal
| _ -> Glyph.ExtensionMethodPublic
| FSharpGlyph.Error -> Glyph.Error
[<RequireQualifiedAccess>]
module String =
let getLines (str: string) =
use reader = new StringReader(str)
[| let mutable line = reader.ReadLine()
while not (isNull line) do
yield line
line <- reader.ReadLine()
if str.EndsWith("\n") then
// last trailing space not returned
// http://stackoverflow.com/questions/19365404/stringreader-omits-trailing-linebreak
yield String.Empty
|]
[<RequireQualifiedAccess>]
module Option =
let guard (x: bool) : Option<unit> =
if x then Some() else None
let attempt (f: unit -> 'T) = try Some <| f() with _ -> None
let inline ofNull value =
if obj.ReferenceEquals(value, null) then None else Some value
/// Gets the option if Some x, otherwise try to get another value
let inline orTry f =
function
| Some x -> Some x
| None -> f()
/// Gets the value if Some x, otherwise try to get another value by calling a function
let inline getOrTry f =
function
| Some x -> x
| None -> f()
[<RequireQualifiedAccess>]
module List =
let foldi (folder : 'State -> int -> 'T -> 'State) (state : 'State) (xs : 'T list) =
let mutable state = state
let mutable i = 0
for x in xs do
state <- folder state i x
i <- i + 1
state
[<RequireQualifiedAccess>]
module Seq =
open System.Collections.Immutable
let toImmutableArray (xs: seq<'a>) : ImmutableArray<'a> = xs.ToImmutableArray()
[<RequireQualifiedAccess>]
module Array =
/// Optimized arrays equality. ~100x faster than `array1 = array2` on strings.
/// ~2x faster for floats
/// ~0.8x slower for ints
let areEqual (xs: 'T []) (ys: 'T []) =
match xs, ys with
| null, null -> true
| [||], [||] -> true
| null, _ | _, null -> false
| _ when xs.Length <> ys.Length -> false
| _ ->
let mutable break' = false
let mutable i = 0
let mutable result = true
while i < xs.Length && not break' do
if xs.[i] <> ys.[i] then
break' <- true
result <- false
i <- i + 1
result
/// check if subArray is found in the wholeArray starting
/// at the provided index
let isSubArray (subArray: 'T []) (wholeArray:'T []) index =
if isNull subArray || isNull wholeArray then false
elif subArray.Length = 0 then true
elif subArray.Length > wholeArray.Length then false
elif subArray.Length = wholeArray.Length then areEqual subArray wholeArray else
let rec loop subidx idx =
if subidx = subArray.Length then true
elif subArray.[subidx] = wholeArray.[idx] then loop (subidx+1) (idx+1)
else false
loop 0 index
/// Returns true if one array has another as its subset from index 0.
let startsWith (prefix: _ []) (whole: _ []) =
isSubArray prefix whole 0
/// Returns true if one array has trailing elements equal to another's.
let endsWith (suffix: _ []) (whole: _ []) =
isSubArray suffix whole (whole.Length-suffix.Length)
\ No newline at end of file
......@@ -3,7 +3,6 @@ module Microsoft.VisualStudio.FSharp.Editor.Pervasive
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open System.Diagnostics
......@@ -20,36 +19,8 @@ let isScriptFile (filePath:string) =
/// Path combination operator
let (</>) path1 path2 = Path.Combine (path1, path2)
type internal ISetThemeColors = abstract member SetColors: unit -> unit
type Path with
static member GetFullPathSafe path =
try Path.GetFullPath path
with _ -> path
static member GetFileNameSafe path =
try Path.GetFileName path
with _ -> path
[<RequireQualifiedAccess>]
module String =
let getLines (str: string) =
use reader = new StringReader(str)
[| let mutable line = reader.ReadLine()
while not (isNull line) do
yield line
line <- reader.ReadLine()
if str.EndsWith("\n") then
// last trailing space not returned
// http://stackoverflow.com/questions/19365404/stringreader-omits-trailing-linebreak
yield String.Empty
|]
type System.IServiceProvider with
member x.GetService<'T>() = x.GetService(typeof<'T>) :?> 'T
member x.GetService<'S, 'T>() = x.GetService(typeof<'S>) :?> 'T
[<Sealed>]
type MaybeBuilder () =
......@@ -271,62 +242,3 @@ type AsyncBuilder with
member __.ReturnFrom(computation: System.Threading.Tasks.Task<'a>): Async<'a> = Async.AwaitTask computation
module Option =
let guard (x: bool) : Option<unit> =
if x then Some() else None
module List =
let foldi (folder : 'State -> int -> 'T -> 'State) (state : 'State) (xs : 'T list) =
let mutable state = state
let mutable i = 0
for x in xs do
state <- folder state i x
i <- i + 1
state
module Seq =
open System.Collections.Immutable
let toImmutableArray (xs: seq<'a>) : ImmutableArray<'a> = xs.ToImmutableArray()
module Array =
/// Optimized arrays equality. ~100x faster than `array1 = array2` on strings.
/// ~2x faster for floats
/// ~0.8x slower for ints
let areEqual (xs: 'T []) (ys: 'T []) =
match xs, ys with
| null, null -> true
| [||], [||] -> true
| null, _ | _, null -> false
| _ when xs.Length <> ys.Length -> false
| _ ->
let mutable break' = false
let mutable i = 0
let mutable result = true
while i < xs.Length && not break' do
if xs.[i] <> ys.[i] then
break' <- true
result <- false
i <- i + 1
result
/// check if subArray is found in the wholeArray starting
/// at the provided index
let isSubArray (subArray: 'T []) (wholeArray:'T []) index =
if isNull subArray || isNull wholeArray then false
elif subArray.Length = 0 then true
elif subArray.Length > wholeArray.Length then false
elif subArray.Length = wholeArray.Length then areEqual subArray wholeArray else
let rec loop subidx idx =
if subidx = subArray.Length then true
elif subArray.[subidx] = wholeArray.[idx] then loop (subidx+1) (idx+1)
else false
loop 0 index
/// Returns true if one array has another as its subset from index 0.
let startsWith (prefix: _ []) (whole: _ []) =
isSubArray prefix whole 0
/// Returns true if one array has trailing elements equal to another's.
let endsWith (suffix: _ []) (whole: _ []) =
isSubArray suffix whole (whole.Length-suffix.Length)
\ No newline at end of file
......@@ -13,9 +13,11 @@ open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Layout
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.VisualStudio.FSharp.LanguageService
module internal CommonRoslynHelpers =
module internal RoslynHelpers =
let FSharpRangeToTextSpan(sourceText: SourceText, range: range) =
// Roslyn TextLineCollection is zero-based, F# range lines are one-based
......@@ -44,6 +46,8 @@ module internal CommonRoslynHelpers =
Assert.Exception(task.Exception.GetBaseException())
raise(task.Exception.GetBaseException())
/// maps from `LayoutTag` of the F# Compiler to Roslyn `TextTags` for use in tooltips
let roslynTag = function
| LayoutTag.ActivePatternCase
......@@ -113,202 +117,13 @@ module internal CommonRoslynHelpers =
let descriptor = new DiagnosticDescriptor(id, emptyString, description, error.Subcategory, severity, true, emptyString, String.Empty, customTags)
Diagnostic.Create(descriptor, location)
let inline (|Public|Internal|Protected|Private|) (a: FSharpAccessibility option) =
match a with
| None -> Public
| Some a ->
if a.IsPublic then Public
elif a.IsInternal then Internal
elif a.IsPrivate then Private
else Protected
let FSharpGlyphToRoslynGlyph (glyph: FSharpGlyph, accessibility: FSharpAccessibility option) =
match glyph with
| FSharpGlyph.Class
| FSharpGlyph.Exception
| FSharpGlyph.Typedef
| FSharpGlyph.Type ->
match accessibility with
| Public -> Glyph.ClassPublic
| Internal -> Glyph.ClassInternal
| Protected -> Glyph.ClassProtected
| Private -> Glyph.ClassPrivate
| FSharpGlyph.Constant ->
match accessibility with
| Public -> Glyph.ConstantPublic
| Internal -> Glyph.ConstantInternal
| Protected -> Glyph.ConstantProtected
| Private -> Glyph.ConstantPrivate
| FSharpGlyph.Delegate ->
match accessibility with
| Public -> Glyph.DelegatePublic
| Internal -> Glyph.DelegateInternal
| Protected -> Glyph.DelegateProtected
| Private -> Glyph.DelegatePrivate
| FSharpGlyph.Enum
| FSharpGlyph.Union ->
match accessibility with
| Public -> Glyph.EnumPublic
| Internal -> Glyph.EnumInternal
| Protected -> Glyph.EnumProtected
| Private -> Glyph.EnumPrivate
| FSharpGlyph.EnumMember -> Glyph.EnumMember
| FSharpGlyph.Event ->
match accessibility with
| Public -> Glyph.EventPublic
| Internal -> Glyph.EventInternal
| Protected -> Glyph.EventProtected
| Private -> Glyph.EventPrivate
| FSharpGlyph.Field ->
match accessibility with
| Public -> Glyph.FieldPublic
| Internal -> Glyph.FieldInternal
| Protected -> Glyph.FieldProtected
| Private -> Glyph.FieldPrivate
| FSharpGlyph.Interface ->
match accessibility with
| Public -> Glyph.InterfacePublic
| Internal -> Glyph.InterfaceInternal
| Protected -> Glyph.InterfaceProtected
| Private -> Glyph.InterfacePrivate
| FSharpGlyph.Method
| FSharpGlyph.OverridenMethod ->
match accessibility with
| Public -> Glyph.MethodPublic
| Internal -> Glyph.MethodInternal
| Protected -> Glyph.MethodProtected
| Private -> Glyph.MethodPrivate
| FSharpGlyph.ExtensionMethod ->
match accessibility with
| Public -> Glyph.ExtensionMethodPublic
| Internal -> Glyph.ExtensionMethodInternal
| Protected -> Glyph.ExtensionMethodProtected
| Private -> Glyph.ExtensionMethodPrivate
| FSharpGlyph.Module ->
match accessibility with
| Public -> Glyph.ModulePublic
| Internal -> Glyph.ModuleInternal
| Protected -> Glyph.ModuleProtected
| Private -> Glyph.ModulePrivate
| FSharpGlyph.NameSpace -> Glyph.Namespace
| FSharpGlyph.Property ->
match accessibility with
| Public -> Glyph.PropertyPublic
| Internal -> Glyph.PropertyInternal
| Protected -> Glyph.PropertyProtected
| Private -> Glyph.PropertyPrivate
| FSharpGlyph.Struct ->
match accessibility with
| Public -> Glyph.StructurePublic
| Internal -> Glyph.StructureInternal
| Protected -> Glyph.StructureProtected
| Private -> Glyph.StructurePrivate
| FSharpGlyph.Variable -> Glyph.Local
| FSharpGlyph.Error -> Glyph.Error
let GetGlyphForSymbol (symbol: FSharpSymbol, kind: LexerSymbolKind) =
match kind with
| LexerSymbolKind.Operator -> Glyph.Operator
| _ ->
match symbol with
| :? FSharpUnionCase as x ->
match Some x.Accessibility with
| Public -> Glyph.EnumPublic
| Internal -> Glyph.EnumInternal
| Protected -> Glyph.EnumProtected
| Private -> Glyph.EnumPrivate
| :? FSharpActivePatternCase -> Glyph.EnumPublic
| :? FSharpField as x ->
if x.IsLiteral then
match Some x.Accessibility with
| Public -> Glyph.ConstantPublic
| Internal -> Glyph.ConstantInternal
| Protected -> Glyph.ConstantProtected
| Private -> Glyph.ConstantPrivate
else
match Some x.Accessibility with
| Public -> Glyph.FieldPublic
| Internal -> Glyph.FieldInternal
| Protected -> Glyph.FieldProtected
| Private -> Glyph.FieldPrivate
| :? FSharpParameter -> Glyph.Parameter
| :? FSharpMemberOrFunctionOrValue as x ->
if x.LiteralValue.IsSome then
match Some x.Accessibility with
| Public -> Glyph.ConstantPublic
| Internal -> Glyph.ConstantInternal
| Protected -> Glyph.ConstantProtected
| Private -> Glyph.ConstantPrivate
elif x.IsExtensionMember then
match Some x.Accessibility with
| Public -> Glyph.ExtensionMethodPublic
| Internal -> Glyph.ExtensionMethodInternal
| Protected -> Glyph.ExtensionMethodProtected
| Private -> Glyph.ExtensionMethodPrivate
elif x.IsProperty || x.IsPropertyGetterMethod || x.IsPropertySetterMethod then
match Some x.Accessibility with
| Public -> Glyph.PropertyPublic
| Internal -> Glyph.PropertyInternal
| Protected -> Glyph.PropertyProtected
| Private -> Glyph.PropertyPrivate
elif x.IsEvent then
match Some x.Accessibility with
| Public -> Glyph.EventPublic
| Internal -> Glyph.EventInternal
| Protected -> Glyph.EventProtected
| Private -> Glyph.EventPrivate
else
match Some x.Accessibility with
| Public -> Glyph.MethodPublic
| Internal -> Glyph.MethodInternal
| Protected -> Glyph.MethodProtected
| Private -> Glyph.MethodPrivate
| :? FSharpEntity as x ->
if x.IsValueType then
match Some x.Accessibility with
| Public -> Glyph.StructurePublic
| Internal -> Glyph.StructureInternal
| Protected -> Glyph.StructureProtected
| Private -> Glyph.StructurePrivate
elif x.IsFSharpModule then
match Some x.Accessibility with
| Public -> Glyph.ModulePublic
| Internal -> Glyph.ModuleInternal
| Protected -> Glyph.ModuleProtected
| Private -> Glyph.ModulePrivate
elif x.IsEnum || x.IsFSharpUnion then
match Some x.Accessibility with
| Public -> Glyph.EnumPublic
| Internal -> Glyph.EnumInternal
| Protected -> Glyph.EnumProtected
| Private -> Glyph.EnumPrivate
elif x.IsInterface then
match Some x.Accessibility with
| Public -> Glyph.InterfacePublic
| Internal -> Glyph.InterfaceInternal
| Protected -> Glyph.InterfaceProtected
| Private -> Glyph.InterfacePrivate
elif x.IsDelegate then
match Some x.Accessibility with
| Public -> Glyph.DelegatePublic
| Internal -> Glyph.DelegateInternal
| Protected -> Glyph.DelegateProtected
| Private -> Glyph.DelegatePrivate
elif x.IsNamespace then
Glyph.Namespace
else
match Some x.Accessibility with
| Public -> Glyph.ClassPublic
| Internal -> Glyph.ClassInternal
| Protected -> Glyph.ClassProtected
| Private -> Glyph.ClassPrivate
| _ -> Glyph.None
let RangeToLocation (r: range, sourceText: SourceText, filePath: string) : Location =
let linePositionSpan = LinePositionSpan(LinePosition(Line.toZ r.StartLine, r.StartColumn), LinePosition(Line.toZ r.EndLine, r.EndColumn))
let textSpan = sourceText.Lines.GetTextSpan linePositionSpan
Location.Create(filePath, textSpan, linePositionSpan)
module internal OpenDeclarationHelper =
/// <summary>
/// Inserts open declaration into `SourceText`.
......
......@@ -21,6 +21,8 @@ open Microsoft.VisualStudio.Shell.Interop
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
open Tokenizer
type internal FSharpCompletionProvider
(
......@@ -140,7 +142,7 @@ type internal FSharpCompletionProvider
let maxHints = if mruItems.Values.Count = 0 then 0 else Seq.max mruItems.Values
sortedDeclItems |> Array.iteri (fun number declItem ->
let glyph = CommonRoslynHelpers.FSharpGlyphToRoslynGlyph (declItem.Glyph, declItem.Accessibility)
let glyph = FSharpGlyphToRoslynGlyph (declItem.Glyph, declItem.Accessibility)
let name =
match entityKind, declItem.NamespaceToOpen with
| Some EntityKind.Attribute, _ when declItem.IsAttribute && declItem.Name.EndsWith "Attribute" ->
......@@ -226,7 +228,7 @@ type internal FSharpCompletionProvider
FSharpCompletionProvider.ProvideCompletionsAsyncAux(checkerProvider.Checker, sourceText, context.Position, options,
document.FilePath, textVersion.GetHashCode(), getAllSymbols)
context.AddItems(results)
} |> Async.Ignore |> CommonRoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
} |> Async.Ignore |> RoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
override this.GetDescriptionAsync(_: Document, completionItem: Completion.CompletionItem, cancellationToken: CancellationToken): Task<CompletionDescription> =
async {
......@@ -234,13 +236,13 @@ type internal FSharpCompletionProvider
if exists then
let! description = declarationItem.StructuredDescriptionTextAsync
let documentation = List()
let collector = CommonRoslynHelpers.CollectTaggedText documentation
let collector = RoslynHelpers.CollectTaggedText documentation
// mix main description and xmldoc by using one collector
XmlDocumentation.BuildDataTipText(documentationBuilder, collector, collector, description)
return CompletionDescription.Create(documentation.ToImmutableArray())
else
return CompletionDescription.Empty
} |> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
} |> RoslynHelpers.StartAsyncAsTask cancellationToken
override this.GetChangeAsync(document, item, _, cancellationToken) : Task<CompletionChange> =
async {
......@@ -285,4 +287,4 @@ type internal FSharpCompletionProvider
}
|> Async.map (Option.defaultValue (CompletionChange.Create(TextChange(item.Span, nameInCode))))
} |> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
\ No newline at end of file
} |> RoslynHelpers.StartAsyncAsTask cancellationToken
\ No newline at end of file
......@@ -36,12 +36,12 @@ type internal FSharpCompletionService
.WithDismissIfLastCharacterDeleted(true)
.WithDefaultEnterKeyRule(EnterKeyRule.Never)
override this.Language = FSharpCommonConstants.FSharpLanguageName
override this.Language = FSharpConstants.FSharpLanguageName
override this.GetBuiltInProviders() = builtInProviders
override this.GetRules() = completionRules
[<Shared>]
[<ExportLanguageServiceFactory(typeof<CompletionService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageServiceFactory(typeof<CompletionService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpCompletionServiceFactory
[<ImportingConstructor>]
(
......
......@@ -85,7 +85,7 @@ module internal CompletionUtils =
let shouldProvideCompletion (documentId: DocumentId, filePath: string, defines: string list, text: SourceText, position: int) : bool =
let textLines = text.Lines
let triggerLine = textLines.GetLineFromPosition position
let colorizationData = CommonHelpers.getColorizationData(documentId, text, triggerLine.Span, Some filePath, defines, CancellationToken.None)
let colorizationData = Tokenizer.getColorizationData(documentId, text, triggerLine.Span, Some filePath, defines, CancellationToken.None)
colorizationData.Count = 0 || // we should provide completion at the start of empty line, where there are no tokens at all
colorizationData.Exists (fun classifiedSpan ->
classifiedSpan.TextSpan.IntersectsWith position &&
......
......@@ -58,7 +58,7 @@ type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoM
let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document)
let textLines = text.Lines
let triggerLine = textLines.GetLineFromPosition(position)
CommonHelpers.getColorizationData(documentId, text, triggerLine.Span, Some document.FilePath, defines, CancellationToken.None)
Tokenizer.getColorizationData(documentId, text, triggerLine.Span, Some document.FilePath, defines, CancellationToken.None)
let isInStringLiteral(text: SourceText, position: int) : bool =
getColorizationData(text, position)
......@@ -143,7 +143,7 @@ type internal HashDirectiveCompletionProvider(workspace: Workspace, projectInfoM
context.AddItems(helper.GetItems(pathThroughLastSlash, documentPath))
}
|> Async.Ignore
|> CommonRoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
|> RoslynHelpers.StartAsyncUnitAsTask context.CancellationToken
override __.IsInsertionTrigger(text, position, _) =
// Bring up completion when the user types a quote (i.e.: #r "), or if they type a slash
......
......@@ -20,7 +20,7 @@ open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
[<Shared>]
[<ExportSignatureHelpProvider("FSharpSignatureHelpProvider", FSharpCommonConstants.FSharpLanguageName)>]
[<ExportSignatureHelpProvider("FSharpSignatureHelpProvider", FSharpConstants.FSharpLanguageName)>]
type internal FSharpSignatureHelpProvider
[<ImportingConstructor>]
(
......@@ -159,16 +159,16 @@ type internal FSharpSignatureHelpProvider
// Create the documentation. Note, do this on the background thread, since doing it in the documentationBuild fails to build the XML index
let mainDescription = List()
let documentation = List()
XmlDocumentation.BuildMethodOverloadTipText(documentationBuilder, CommonRoslynHelpers.CollectTaggedText mainDescription, CommonRoslynHelpers.CollectTaggedText documentation, method.StructuredDescription, false)
XmlDocumentation.BuildMethodOverloadTipText(documentationBuilder, RoslynHelpers.CollectTaggedText mainDescription, RoslynHelpers.CollectTaggedText documentation, method.StructuredDescription, false)
let parameters =
let parameters = if isStaticArgTip then method.StaticParameters else method.Parameters
[| for p in parameters do
let doc = List()
// FSROSLYNTODO: compute the proper help text for parameters, c.f. AppendParameter in XmlDocumentation.fs
XmlDocumentation.BuildMethodParamText(documentationBuilder, CommonRoslynHelpers.CollectTaggedText doc, method.XmlDoc, p.ParameterName)
XmlDocumentation.BuildMethodParamText(documentationBuilder, RoslynHelpers.CollectTaggedText doc, method.XmlDoc, p.ParameterName)
let parts = List()
renderL (taggedTextListR (CommonRoslynHelpers.CollectTaggedText parts)) p.StructuredDisplay |> ignore
renderL (taggedTextListR (RoslynHelpers.CollectTaggedText parts)) p.StructuredDisplay |> ignore
yield (p.ParameterName, p.IsOptional, doc, parts)
|]
......@@ -221,7 +221,7 @@ type internal FSharpSignatureHelpProvider
return! None
}
|> Async.map Option.toObj
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
open System.ComponentModel.Composition
open Microsoft.VisualStudio.Utilities
......@@ -232,7 +232,7 @@ open Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.SignatureHelp.Pre
// Enable colorized signature help for F# buffers
[<Export(typeof<IClassifierProvider>)>]
[<ContentType(FSharpCommonConstants.FSharpSignatureHelpContentTypeName)>]
[<ContentType(FSharpConstants.FSharpSignatureHelpContentTypeName)>]
type internal FSharpSignatureHelpClassifierProvider [<ImportingConstructor>] (typeMap) =
interface IClassifierProvider with
override __.GetClassifier (buffer: ITextBuffer) =
......
......@@ -17,7 +17,7 @@ open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.FSharp.Compiler.Range
[<Shared>]
[<ExportLanguageService(typeof<IBreakpointResolutionService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<IBreakpointResolutionService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpBreakpointResolutionService
[<ImportingConstructor>]
(
......@@ -45,10 +45,10 @@ type internal FSharpBreakpointResolutionService
let! options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject(document)
let! sourceText = document.GetTextAsync(cancellationToken)
let! range = FSharpBreakpointResolutionService.GetBreakpointLocation(checkerProvider.Checker, sourceText, document.Name, textSpan, options)
return BreakpointResolutionResult.CreateSpanResult(document, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
return BreakpointResolutionResult.CreateSpanResult(document, RoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
}
|> Async.map Option.toObj
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
// FSROSLYNTODO: enable placing breakpoints by when user suplies fully-qualified function names
member this.ResolveBreakpointsAsync(_, _, _): Task<IEnumerable<BreakpointResolutionResult>> =
......
......@@ -17,7 +17,7 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.VisualStudio.FSharp.LanguageService
[<Shared>]
[<ExportLanguageService(typeof<ILanguageDebugInfoService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<ILanguageDebugInfoService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpLanguageDebugInfoService [<ImportingConstructor>](projectInfoManager: ProjectInfoManager) =
static member GetDataTipInformation(sourceText: SourceText, position: int, tokens: List<ClassifiedSpan>): TextSpan option =
......@@ -55,13 +55,13 @@ type internal FSharpLanguageDebugInfoService [<ImportingConstructor>](projectInf
let defines = projectInfoManager.GetCompilationDefinesForEditingDocument(document)
let! sourceText = document.GetTextAsync(cancellationToken)
let textSpan = TextSpan.FromBounds(0, sourceText.Length)
let tokens = CommonHelpers.getColorizationData(document.Id, sourceText, textSpan, Some(document.Name), defines, cancellationToken)
let tokens = Tokenizer.getColorizationData(document.Id, sourceText, textSpan, Some(document.Name), defines, cancellationToken)
let result =
match FSharpLanguageDebugInfoService.GetDataTipInformation(sourceText, position, tokens) with
| None -> DebugDataTipInfo()
| Some textSpan -> DebugDataTipInfo(textSpan, sourceText.GetSubText(textSpan).ToString())
return result
}
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
\ No newline at end of file
......@@ -26,7 +26,7 @@ type internal DiagnosticsType =
| Syntax
| Semantic
[<DiagnosticAnalyzer(FSharpCommonConstants.FSharpLanguageName)>]
[<DiagnosticAnalyzer(FSharpConstants.FSharpLanguageName)>]
type internal FSharpDocumentDiagnosticAnalyzer() =
inherit DocumentDiagnosticAnalyzer()
......@@ -103,12 +103,12 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
TextSpan.FromBounds(start, sourceText.Length)
let location = Location.Create(filePath, correctedTextSpan , linePositionSpan)
Some(CommonRoslynHelpers.ConvertError(error, location)))
Some(RoslynHelpers.ConvertError(error, location)))
|> Seq.toImmutableArray
return results
}
override this.SupportedDiagnostics = CommonRoslynHelpers.SupportedDiagnostics()
override this.SupportedDiagnostics = RoslynHelpers.SupportedDiagnostics()
override this.AnalyzeSyntaxAsync(document: Document, cancellationToken: CancellationToken): Task<ImmutableArray<Diagnostic>> =
let projectInfoManager = getProjectInfoManager document
......@@ -121,7 +121,7 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
|> liftAsync
}
|> Async.map (Option.defaultValue ImmutableArray<Diagnostic>.Empty)
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
override this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task<ImmutableArray<Diagnostic>> =
let projectInfoManager = getProjectInfoManager document
......@@ -134,7 +134,7 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
|> liftAsync
}
|> Async.map (Option.defaultValue ImmutableArray<Diagnostic>.Empty)
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
interface IBuiltInAnalyzer with
member __.GetAnalyzerCategory() : DiagnosticAnalyzerCategory = DiagnosticAnalyzerCategory.SemanticDocumentAnalysis
......
......@@ -108,7 +108,7 @@ type internal SimplifyNameDiagnosticAnalyzer() =
result.Add(
Diagnostic.Create(
Descriptor,
CommonRoslynHelpers.RangeToLocation(unnecessaryRange, sourceText, document.FilePath),
RoslynHelpers.RangeToLocation(unnecessaryRange, sourceText, document.FilePath),
properties = (dict [SimplifyNameDiagnosticAnalyzer.LongIdentPropertyKey, relativeName]).ToImmutableDictionary()))
let diagnostics = result.ToImmutableArray()
......@@ -118,7 +118,7 @@ type internal SimplifyNameDiagnosticAnalyzer() =
finally guard.Release() |> ignore
}
|> Async.map (Option.defaultValue ImmutableArray.Empty)
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
interface IBuiltInAnalyzer with
member __.OpenFileOnly _ = true
......
......@@ -8,14 +8,17 @@ open System.Threading
open System.Threading.Tasks
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Text
open Microsoft.CodeAnalysis.Diagnostics
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
open Symbols
module private UnusedOpens =
open Microsoft.CodeAnalysis.Text
let rec visitSynModuleOrNamespaceDecls (parent: Ast.LongIdent) decls : (Set<string> * range) list =
[ for decl in decls do
......@@ -70,7 +73,7 @@ module private UnusedOpens =
| None -> []
let symbolIsFullyQualified (sourceText: SourceText) (sym: FSharpSymbolUse) (fullName: string) =
match CommonRoslynHelpers.TryFSharpRangeToTextSpan(sourceText, sym.RangeAlternate) with
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, sym.RangeAlternate) with
| Some span // check that the symbol hasn't provided an invalid span
when sourceText.Length < span.Start
|| sourceText.Length < span.End -> false
......@@ -135,7 +138,7 @@ module private UnusedOpens =
let openStatements = getOpenStatements parsedInput
openStatements |> filter |> List.map snd
[<DiagnosticAnalyzer(FSharpCommonConstants.FSharpLanguageName)>]
[<DiagnosticAnalyzer(FSharpConstants.FSharpLanguageName)>]
type internal UnusedOpensDiagnosticAnalyzer() =
inherit DocumentDiagnosticAnalyzer()
......@@ -175,11 +178,11 @@ type internal UnusedOpensDiagnosticAnalyzer() =
|> List.map (fun m ->
Diagnostic.Create(
Descriptor,
CommonRoslynHelpers.RangeToLocation(m, sourceText, document.FilePath)))
RoslynHelpers.RangeToLocation(m, sourceText, document.FilePath)))
|> Seq.toImmutableArray
}
|> Async.map (Option.defaultValue ImmutableArray.Empty)
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
interface IBuiltInAnalyzer with
member __.OpenFileOnly _ = true
......
......@@ -21,7 +21,7 @@ type internal FSharpHighlightSpan =
override this.ToString() = sprintf "%+A" this
[<Shared>]
[<ExportLanguageService(typeof<IDocumentHighlightsService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<IDocumentHighlightsService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpDocumentHighlightsService [<ImportingConstructor>] (checkerProvider: FSharpCheckerProvider, projectInfoManager: ProjectInfoManager) =
/// Fix invalid spans if they appear to have redundant suffix and prefix.
......@@ -56,14 +56,14 @@ type internal FSharpDocumentHighlightsService [<ImportingConstructor>] (checkerP
let textLine = sourceText.Lines.GetLineFromPosition(position)
let textLinePos = sourceText.Lines.GetLinePosition(position)
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! symbol = CommonHelpers.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(filePath, textVersionHash, sourceText.ToString(), options, allowStaleResults = true)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland)
let! symbolUses = checkFileResults.GetUsesOfSymbolInFile(symbolUse.Symbol) |> liftAsync
return
[| for symbolUse in symbolUses do
yield { IsDefinition = symbolUse.IsFromDefinition
TextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) } |]
TextSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate) } |]
|> fixInvalidSymbolSpans sourceText symbol.Ident.idText
}
......@@ -86,4 +86,4 @@ type internal FSharpDocumentHighlightsService [<ImportingConstructor>] (checkerP
return ImmutableArray.Create(DocumentHighlights(document, highlightSpans))
}
|> Async.map (Option.defaultValue ImmutableArray<DocumentHighlights>.Empty)
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
......@@ -33,15 +33,19 @@
<Compile Include="srFSharp.Editor.fs" />
<Compile Include="Common\AssemblyInfo.fs" />
<Compile Include="Common\Pervasive.fs" />
<Compile Include="Common\CommonConstants.fs" />
<Compile Include="Common\Extensions.fs" />
<Compile Include="Common\Constants.fs" />
<Compile Include="Common\Logging.fs" />
<Compile Include="Common\CommonHelpers.fs" />
<Compile Include="Common\CommonRoslynHelpers.fs" />
<Compile Include="Common\RoslynHelpers.fs" />
<Compile Include="Common\CodeAnalysisExtensions.fs" />
<Compile Include="Common\ContentType.fs" />
<Compile Include="Common\LanguageService.fs" />
<Compile Include="Common\SymbolHelpers.fs" />
<Compile Include="Common\AssemblyContentProvider.fs" />
<Compile Include="LanguageService\Tokenizer.fs" />
<Compile Include="LanguageService\Symbols.fs" />
<Compile Include="LanguageService\TypedAstUtils.fs" />
<Compile Include="LanguageService\FSharpCheckerExtensions.fs" />
<Compile Include="LanguageService\LanguageService.fs" />
<Compile Include="LanguageService\AssemblyContentProvider.fs" />
<Compile Include="LanguageService\SymbolHelpers.fs" />
<Compile Include="Properties\IntelliSensePropertyPage.fs" />
<Compile Include="Classification\ClassificationDefinitions.fs" />
<Compile Include="Classification\ColorizationService.fs" />
......@@ -106,7 +110,6 @@
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="PresentationFramework" />
......@@ -120,7 +123,6 @@
<Reference Include="PresentationCore" />
<Reference Include="System.ComponentModel.Composition" />
</ItemGroup>
<ItemGroup>
<Reference Include="EnvDTE">
<HintPath>$(FSharpSourcesRoot)\..\packages\EnvDTE.8.0.1\lib\net10\EnvDTE.dll</HintPath>
......
......@@ -7,7 +7,7 @@ open System.ComponentModel.Composition
open Microsoft.CodeAnalysis.Editor
open Microsoft.FSharp.Compiler.SourceCodeServices
[<ExportBraceMatcher(FSharpCommonConstants.FSharpLanguageName)>]
[<ExportBraceMatcher(FSharpConstants.FSharpLanguageName)>]
type internal FSharpBraceMatchingService
[<ImportingConstructor>]
(
......@@ -18,7 +18,7 @@ type internal FSharpBraceMatchingService
static member GetBraceMatchingResult(checker: FSharpChecker, sourceText, fileName, options, position: int) =
async {
let! matchedBraces = checker.MatchBracesAlternate(fileName, sourceText.ToString(), options)
let isPositionInRange range = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range).Contains(position)
let isPositionInRange range = RoslynHelpers.FSharpRangeToTextSpan(sourceText, range).Contains(position)
return matchedBraces |> Array.tryFind(fun (left, right) -> isPositionInRange left || isPositionInRange right)
}
......@@ -30,8 +30,8 @@ type internal FSharpBraceMatchingService
let! (left, right) = FSharpBraceMatchingService.GetBraceMatchingResult(checkerProvider.Checker, sourceText, document.Name, options, position)
return
BraceMatchingResult(
CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, left),
CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, right))
RoslynHelpers.FSharpRangeToTextSpan(sourceText, left),
RoslynHelpers.FSharpRangeToTextSpan(sourceText, right))
}
|> Async.map Option.toNullable
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
......@@ -13,7 +13,7 @@ open Microsoft.CodeAnalysis.Host.Mef
open Microsoft.CodeAnalysis.Text
[<Shared>]
[<ExportLanguageService(typeof<ISynchronousIndentationService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService(typeof<ISynchronousIndentationService>, FSharpConstants.FSharpLanguageName)>]
type internal FSharpIndentationService() =
static member GetDesiredIndentation(sourceText: SourceText, lineNumber: int, tabSize: int): Option<int> =
......@@ -47,7 +47,7 @@ type internal FSharpIndentationService() =
async {
let! sourceText = document.GetTextAsync(cancellationToken)
let! options = document.GetOptionsAsync(cancellationToken)
let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpCommonConstants.FSharpLanguageName)
let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpConstants.FSharpLanguageName)
return
match FSharpIndentationService.GetDesiredIndentation(sourceText, lineNumber, tabSize) with
......
......@@ -17,6 +17,9 @@ open Microsoft.CodeAnalysis.Text
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
open Tokenizer
open Symbols
type internal FailureInlineRenameInfo private () =
interface IInlineRenameInfo with
......@@ -63,11 +66,11 @@ type internal InlineRenameLocationSet(locationsByDocument: DocumentLocations [],
return
{ new IInlineRenameReplacementInfo with
member __.NewSolution = newSolution
member __.ReplacementTextValid = CommonHelpers.isValidNameForSymbol(symbolKind, symbol, replacementText)
member __.ReplacementTextValid = Tokenizer.isValidNameForSymbol(symbolKind, symbol, replacementText)
member __.DocumentIds = locationsByDocument |> Seq.map (fun doc -> doc.Document.Id)
member __.GetReplacements(documentId) = Seq.empty }
}
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
type internal InlineRenameInfo
(
......@@ -87,8 +90,8 @@ type internal InlineRenameInfo
| _ -> document.GetTextAsync(cancellationToken).Result
let triggerSpan =
let span = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate)
CommonHelpers.fixupSpan(sourceText, span)
let span = RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate)
Tokenizer.fixupSpan(sourceText, span)
let symbolUses =
SymbolHelpers.getSymbolUsesInSolution(symbolUse.Symbol, declLoc, checkFileResults, projectInfoManager, checker, document.Project.Solution)
......@@ -107,7 +110,7 @@ type internal InlineRenameInfo
member __.GetReferenceEditSpan(location, cancellationToken) =
let text = getDocumentText location.Document cancellationToken
CommonHelpers.fixupSpan(text, location.TextSpan)
Tokenizer.fixupSpan(text, location.TextSpan)
member __.GetConflictEditSpan(location, _replacementText, _cancellationToken) = Nullable(location.TextSpan)
......@@ -123,18 +126,18 @@ type internal InlineRenameInfo
let locations =
symbolUses
|> Array.map (fun symbolUse ->
let textSpan = CommonHelpers.fixupSpan(sourceText, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
let textSpan = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
InlineRenameLocation(document, textSpan))
return { Document = document; Locations = locations }
})
|> Async.Parallel
return InlineRenameLocationSet(locationsByDocument, document.Project.Solution, lexerSymbol.Kind, symbolUse.Symbol) :> IInlineRenameLocationSet
} |> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
} |> RoslynHelpers.StartAsyncAsTask(cancellationToken)
member __.TryOnBeforeGlobalSymbolRenamed(_workspace, _changedDocumentIDs, _replacementText) = true
member __.TryOnAfterGlobalSymbolRenamed(_workspace, _changedDocumentIDs, _replacementText) = true
[<ExportLanguageService(typeof<IEditorInlineRenameService>, FSharpCommonConstants.FSharpLanguageName); Shared>]
[<ExportLanguageService(typeof<IEditorInlineRenameService>, FSharpConstants.FSharpLanguageName); Shared>]
type internal InlineRenameService
[<ImportingConstructor>]
(
......@@ -149,7 +152,7 @@ type internal InlineRenameService
let textLine = sourceText.Lines.GetLineFromPosition(position)
let textLinePos = sourceText.Lines.GetLinePosition(position)
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! symbol = CommonHelpers.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, allowStaleResults = true)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(fcsTextLineNumber, symbol.Ident.idRange.EndColumn, textLine.Text.ToString(), symbol.FullIsland)
let! declLoc = symbolUse.GetDeclarationLocation(document)
......@@ -165,4 +168,4 @@ type internal InlineRenameService
return! InlineRenameService.GetInlineRenameInfo(checkerProvider.Checker, projectInfoManager, document, sourceText, position, defines, options)
}
|> Async.map (Option.defaultValue FailureInlineRenameInfo.Instance)
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
[<AutoOpen>]
module internal Microsoft.VisualStudio.FSharp.Editor.FSharpCheckerExtensions
open System
open System.Threading.Tasks
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Text
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.SourceCodeServices
open Tokenizer
open Symbols
open TypedAstUtils
type CheckResults =
| Ready of (FSharpParseFileResults * FSharpCheckFileResults) option
| StillRunning of Async<(FSharpParseFileResults * FSharpCheckFileResults) option>
type FSharpChecker with
member this.ParseDocument(document: Document, options: FSharpProjectOptions, sourceText: string) =
asyncMaybe {
let! fileParseResults = this.ParseFileInProject(document.FilePath, sourceText, options) |> liftAsync
return! fileParseResults.ParseTree
}
member this.ParseDocument(document: Document, options: FSharpProjectOptions, ?sourceText: SourceText) =
asyncMaybe {
let! sourceText =
match sourceText with
| Some x -> Task.FromResult x
| None -> document.GetTextAsync()
return! this.ParseDocument(document, options, sourceText.ToString())
}
member this.ParseAndCheckDocument(filePath: string, textVersionHash: int, sourceText: string, options: FSharpProjectOptions, allowStaleResults: bool) : Async<(FSharpParseFileResults * Ast.ParsedInput * FSharpCheckFileResults) option> =
let parseAndCheckFile =
async {
let! parseResults, checkFileAnswer = this.ParseAndCheckFileInProject(filePath, textVersionHash, sourceText, options)
return
match checkFileAnswer with
| FSharpCheckFileAnswer.Aborted ->
None
| FSharpCheckFileAnswer.Succeeded(checkFileResults) ->
Some (parseResults, checkFileResults)
}
let tryGetFreshResultsWithTimeout() : Async<CheckResults> =
async {
try
let! worker = Async.StartChild(parseAndCheckFile, 2000)
let! result = worker
return Ready result
with :? TimeoutException ->
return StillRunning parseAndCheckFile
}
let bindParsedInput(results: (FSharpParseFileResults * FSharpCheckFileResults) option) =
match results with
| Some(parseResults, checkResults) ->
match parseResults.ParseTree with
| Some parsedInput -> Some (parseResults, parsedInput, checkResults)
| None -> None
| None -> None
if allowStaleResults then
async {
let! freshResults = tryGetFreshResultsWithTimeout()
let! results =
match freshResults with
| Ready x -> async.Return x
| StillRunning worker ->
async {
match allowStaleResults, this.TryGetRecentCheckResultsForFile(filePath, options) with
| true, Some (parseResults, checkFileResults, _) ->
return Some (parseResults, checkFileResults)
| _ ->
return! worker
}
return bindParsedInput results
}
else parseAndCheckFile |> Async.map bindParsedInput
member this.ParseAndCheckDocument(document: Document, options: FSharpProjectOptions, allowStaleResults: bool, ?sourceText: SourceText) : Async<(FSharpParseFileResults * Ast.ParsedInput * FSharpCheckFileResults) option> =
async {
let! cancellationToken = Async.CancellationToken
let! sourceText =
match sourceText with
| Some x -> Task.FromResult x
| None -> document.GetTextAsync()
let! textVersion = document.GetTextVersionAsync(cancellationToken)
return! this.ParseAndCheckDocument(document.FilePath, textVersion.GetHashCode(), sourceText.ToString(), options, allowStaleResults)
}
member self.TryParseAndCheckFileInProject (projectOptions, fileName, source) = async {
let! (parseResults, checkAnswer) = self.ParseAndCheckFileInProject (fileName,0, source,projectOptions)
match checkAnswer with
| FSharpCheckFileAnswer.Aborted -> return None
| FSharpCheckFileAnswer.Succeeded checkResults -> return Some (parseResults,checkResults)
}
member self.GetAllUsesOfAllSymbolsInSourceString (projectOptions, fileName, source: string, checkForUnusedOpens) = async {
let! parseAndCheckResults = self.TryParseAndCheckFileInProject (projectOptions, fileName, source)
match parseAndCheckResults with
| None -> return [||]
| Some(_parseResults,checkResults) ->
let! fsharpSymbolsUses = checkResults.GetAllUsesOfAllSymbolsInFile()
let allSymbolsUses =
fsharpSymbolsUses
|> Array.map (fun symbolUse ->
let fullNames =
match symbolUse.Symbol with
// Make sure that unsafe manipulation isn't executed if unused opens are disabled
| _ when not checkForUnusedOpens -> None
| TypedAstPatterns.MemberFunctionOrValue func when func.IsExtensionMember ->
if func.IsProperty then
let fullNames =
[| if func.HasGetterMethod then
yield func.GetterMethod.EnclosingEntity.TryGetFullName()
if func.HasSetterMethod then
yield func.SetterMethod.EnclosingEntity.TryGetFullName()
|]
|> Array.choose id
match fullNames with
| [||] -> None
| _ -> Some fullNames
else
match func.EnclosingEntity with
// C# extension method
| TypedAstPatterns.FSharpEntity TypedAstPatterns.Class ->
let fullName = symbolUse.Symbol.FullName.Split '.'
if fullName.Length > 2 then
(* For C# extension methods FCS returns full name including the class name, like:
Namespace.StaticClass.ExtensionMethod
So, in order to properly detect that "open Namespace" actually opens ExtensionMethod,
we remove "StaticClass" part. This makes C# extension methods looks identically
with F# extension members.
*)
let fullNameWithoutClassName =
Array.append fullName.[0..fullName.Length - 3] fullName.[fullName.Length - 1..]
Some [|String.Join (".", fullNameWithoutClassName)|]
else None
| _ -> None
// Operators
| TypedAstPatterns.MemberFunctionOrValue func ->
match func with
| TypedAstPatterns.Constructor _ ->
// full name of a constructor looks like "UnusedSymbolClassifierTests.PrivateClass.( .ctor )"
// to make well formed full name parts we cut "( .ctor )" from the tail.
let fullName = func.FullName
let ctorSuffix = ".( .ctor )"
let fullName =
if fullName.EndsWith ctorSuffix then
fullName.[0..fullName.Length - ctorSuffix.Length - 1]
else fullName
Some [| fullName |]
| _ ->
Some [| yield func.FullName
match func.TryGetFullCompiledOperatorNameIdents() with
| Some idents -> yield String.concat "." idents
| None -> ()
|]
| TypedAstPatterns.FSharpEntity e ->
match e with
| e, TypedAstPatterns.Attribute, _ ->
e.TryGetFullName ()
|> Option.map (fun fullName ->
[| fullName; fullName.Substring(0, fullName.Length - "Attribute".Length) |])
| e, _, _ ->
e.TryGetFullName () |> Option.map (fun fullName -> [| fullName |])
| TypedAstPatterns.RecordField _
| TypedAstPatterns.UnionCase _ as symbol ->
Some [| let fullName = symbol.FullName
yield fullName
let idents = fullName.Split '.'
// Union cases/Record fields can be accessible without mentioning the enclosing type.
// So we add a FullName without having the type part.
if idents.Length > 1 then
yield String.Join (".", Array.append idents.[0..idents.Length - 3] idents.[idents.Length - 1..])
|]
| _ -> None
|> Option.defaultValue [|symbolUse.Symbol.FullName|]
|> Array.map (fun fullName -> fullName.Split '.')
{ SymbolUse = symbolUse
IsUsed = true
FullNames = fullNames
})
return allSymbolsUses
}
......@@ -33,7 +33,7 @@ open Microsoft.VisualStudio.ComponentModelHost
// Workaround to access non-public settings persistence type.
// GetService( ) with this will work as long as the GUID matches the real type.
[<Guid(FSharpCommonConstants.svsSettingsPersistenceManagerGuidString)>]
[<Guid(FSharpConstants.svsSettingsPersistenceManagerGuidString)>]
type internal SVsSettingsPersistenceManager = class end
// Exposes FSharpChecker as MEF export
......@@ -176,7 +176,7 @@ type internal RoamingProfileStorageLocation(keyName: string) =
match languageName with
| null -> unsubstitutedKeyName
| _ ->
let substituteLanguageName = if languageName = FSharpCommonConstants.FSharpLanguageName then "FSharp" else languageName
let substituteLanguageName = if languageName = FSharpConstants.FSharpLanguageName then "FSharp" else languageName
unsubstitutedKeyName.Replace("%LANGUAGE%", substituteLanguageName)
[<Composition.Shared>]
......@@ -194,9 +194,9 @@ type internal FSharpCheckerWorkspaceServiceFactory
member this.ProjectInfoManager = projectInfoManager }
type
[<Guid(FSharpCommonConstants.packageGuidString)>]
[<Guid(FSharpConstants.packageGuidString)>]
[<ProvideLanguageService(languageService = typeof<FSharpLanguageService>,
strLanguageName = FSharpCommonConstants.FSharpLanguageName,
strLanguageName = FSharpConstants.FSharpLanguageName,
languageResourceID = 100,
MatchBraces = true,
MatchBracesAtCaret = true,
......@@ -214,7 +214,7 @@ type
internal FSharpPackage() =
inherit AbstractPackage<FSharpPackage, FSharpLanguageService>()
override this.RoslynLanguageName = FSharpCommonConstants.FSharpLanguageName
override this.RoslynLanguageName = FSharpConstants.FSharpLanguageName
override this.CreateWorkspace() = this.ComponentModel.GetService<VisualStudioWorkspaceImpl>()
......@@ -226,19 +226,19 @@ type
override this.RegisterMiscellaneousFilesWorkspaceInformation(_) = ()
and
[<Guid(FSharpCommonConstants.languageServiceGuidString)>]
[<Guid(FSharpConstants.languageServiceGuidString)>]
[<ProvideLanguageExtension(typeof<FSharpLanguageService>, ".fs")>]
[<ProvideLanguageExtension(typeof<FSharpLanguageService>, ".fsi")>]
[<ProvideLanguageExtension(typeof<FSharpLanguageService>, ".fsx")>]
[<ProvideLanguageExtension(typeof<FSharpLanguageService>, ".fsscript")>]
[<ProvideLanguageExtension(typeof<FSharpLanguageService>, ".ml")>]
[<ProvideLanguageExtension(typeof<FSharpLanguageService>, ".mli")>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fs", 97)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fsi", 97)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fsx", 97)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fsscript", 97)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".ml", 97)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".mli", 97)>]
[<ProvideEditorExtension(FSharpConstants.editorFactoryGuidString, ".fs", 97)>]
[<ProvideEditorExtension(FSharpConstants.editorFactoryGuidString, ".fsi", 97)>]
[<ProvideEditorExtension(FSharpConstants.editorFactoryGuidString, ".fsx", 97)>]
[<ProvideEditorExtension(FSharpConstants.editorFactoryGuidString, ".fsscript", 97)>]
[<ProvideEditorExtension(FSharpConstants.editorFactoryGuidString, ".ml", 97)>]
[<ProvideEditorExtension(FSharpConstants.editorFactoryGuidString, ".mli", 97)>]
internal FSharpLanguageService(package : FSharpPackage) =
inherit AbstractLanguageService<FSharpPackage, FSharpLanguageService>(package)
......@@ -260,8 +260,8 @@ and
override this.Initialize() =
base.Initialize()
this.Workspace.Options <- this.Workspace.Options.WithChangedOption(Completion.CompletionOptions.BlockForCompletionItems, FSharpCommonConstants.FSharpLanguageName, false)
this.Workspace.Options <- this.Workspace.Options.WithChangedOption(Shared.Options.ServiceFeatureOnOffOptions.ClosedFileDiagnostic, FSharpCommonConstants.FSharpLanguageName, Nullable false)
this.Workspace.Options <- this.Workspace.Options.WithChangedOption(Completion.CompletionOptions.BlockForCompletionItems, FSharpConstants.FSharpLanguageName, false)
this.Workspace.Options <- this.Workspace.Options.WithChangedOption(Shared.Options.ServiceFeatureOnOffOptions.ClosedFileDiagnostic, FSharpConstants.FSharpLanguageName, Nullable false)
this.Workspace.DocumentClosed.Add <| fun args ->
tryRemoveSingleFileProject args.Document.Project.Id
......@@ -331,14 +331,14 @@ and
let projectContext =
projectContextFactory.CreateProjectContext(
FSharpCommonConstants.FSharpLanguageName, projectDisplayName, projectFileName, projectGuid, siteProvider, null, errorReporter)
FSharpConstants.FSharpLanguageName, projectDisplayName, projectFileName, projectGuid, siteProvider, null, errorReporter)
let project = projectContext :?> AbstractProject
this.SyncProject(project, projectContext, site, forceUpdate=false)
site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName,
site.AdviseProjectSiteChanges(FSharpConstants.FSharpLanguageServiceCallbackName,
AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site, forceUpdate=true)))
site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName,
site.AdviseProjectSiteClosed(FSharpConstants.FSharpLanguageServiceCallbackName,
AdviseProjectSiteChanges(fun () ->
projectInfoManager.ClearProjectInfo(project.Id)
project.Disconnect()))
......@@ -363,17 +363,17 @@ and
let projectContextFactory = package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)
let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, projectDisplayName, projectFileName, projectId.Id, hier, null, errorReporter)
let projectContext = projectContextFactory.CreateProjectContext(FSharpConstants.FSharpLanguageName, projectDisplayName, projectFileName, projectId.Id, hier, null, errorReporter)
projectContext.AddSourceFile(fileName)
let project = projectContext :?> AbstractProject
singleFileProjects.[projectId] <- project
override this.ContentTypeName = FSharpCommonConstants.FSharpContentTypeName
override this.LanguageName = FSharpCommonConstants.FSharpLanguageName
override this.RoslynLanguageName = FSharpCommonConstants.FSharpLanguageName
override this.ContentTypeName = FSharpConstants.FSharpContentTypeName
override this.LanguageName = FSharpConstants.FSharpLanguageName
override this.RoslynLanguageName = FSharpConstants.FSharpLanguageName
override this.LanguageServiceId = new Guid(FSharpCommonConstants.languageServiceGuidString)
override this.LanguageServiceId = new Guid(FSharpConstants.languageServiceGuidString)
override this.DebuggerLanguageId = DebuggerEnvironment.GetLanguageID()
override this.CreateContext(_,_,_,_,_) = raise(System.NotImplementedException())
......
......@@ -11,6 +11,8 @@ open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Text
open Microsoft.FSharp.Compiler.SourceCodeServices
open Symbols
module internal SymbolHelpers =
let getSymbolUsesInSolution (symbol: FSharpSymbol, declLoc: SymbolDeclarationLocation, checkFileResults: FSharpCheckFileResults,
......@@ -63,7 +65,7 @@ module internal SymbolHelpers =
do! Option.guard (originalText.Length > 0)
let! options = projectInfoManager.TryGetOptionsForEditingDocumentOrProject document
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, options.OtherOptions |> Seq.toList)
let! symbol = CommonHelpers.getSymbolAtPosition(document.Id, sourceText, symbolSpan.Start, document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, symbolSpan.Start, document.FilePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, options, allowStaleResults = true)
let textLine = sourceText.Lines.GetLineFromPosition(symbolSpan.Start)
let textLinePos = sourceText.Lines.GetLinePosition(symbolSpan.Start)
......@@ -85,10 +87,10 @@ module internal SymbolHelpers =
let! sourceText = document.GetTextAsync(cancellationToken)
let mutable sourceText = sourceText
for symbolUse in symbolUses do
let textSpan = CommonHelpers.fixupSpan(sourceText, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
let textSpan = Tokenizer.fixupSpan(sourceText, RoslynHelpers.FSharpRangeToTextSpan(sourceText, symbolUse.RangeAlternate))
sourceText <- sourceText.Replace(textSpan, newText)
solution <- solution.WithDocumentText(documentId, sourceText)
return solution
} |> CommonRoslynHelpers.StartAsyncAsTask cancellationToken),
} |> RoslynHelpers.StartAsyncAsTask cancellationToken),
originalText
}
[<AutoOpen>]
module internal Microsoft.VisualStudio.FSharp.Editor.Symbols
open System
open System.Collections.Generic
open System.Threading
open System.Threading.Tasks
open System.Runtime.CompilerServices
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Classification
open Microsoft.CodeAnalysis.Text
open Microsoft.VisualStudio.FSharp.LanguageService
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.SourceCodeServices
open System.IO
[<RequireQualifiedAccess; NoComparison>]
type SymbolDeclarationLocation =
| CurrentDocument
| Projects of Project list * isLocalForProject: bool
[<NoComparison>]
type SymbolUse =
{ SymbolUse: FSharpSymbolUse
IsUsed: bool
FullNames: Idents[] }
type FSharpSymbol with
member this.IsInternalToProject =
match this with
| :? FSharpParameter -> true
| :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || not m.Accessibility.IsPublic
| :? FSharpEntity as m -> not m.Accessibility.IsPublic
| :? FSharpGenericParameter -> true
| :? FSharpUnionCase as m -> not m.Accessibility.IsPublic
| :? FSharpField as m -> not m.Accessibility.IsPublic
| _ -> false
type FSharpSymbolUse with
member this.GetDeclarationLocation (currentDocument: Document) : SymbolDeclarationLocation option =
if this.IsPrivateToFile then
Some SymbolDeclarationLocation.CurrentDocument
else
let isSymbolLocalForProject = this.Symbol.IsInternalToProject
let declarationLocation =
match this.Symbol.ImplementationLocation with
| Some x -> Some x
| None -> this.Symbol.DeclarationLocation
match declarationLocation with
| Some loc ->
let filePath = Path.GetFullPathSafe loc.FileName
let isScript = isScriptFile filePath
if isScript && filePath = currentDocument.FilePath then
Some SymbolDeclarationLocation.CurrentDocument
elif isScript then
// The standalone script might include other files via '#load'
// These files appear in project options and the standalone file
// should be treated as an individual project
Some (SymbolDeclarationLocation.Projects ([currentDocument.Project], isSymbolLocalForProject))
else
let projects =
currentDocument.Project.Solution.GetDocumentIdsWithFilePath(filePath)
|> Seq.map (fun x -> x.ProjectId)
|> Seq.distinct
|> Seq.map currentDocument.Project.Solution.GetProject
|> Seq.toList
match projects with
| [] -> None
| projects -> Some (SymbolDeclarationLocation.Projects (projects, isSymbolLocalForProject))
| None -> None
member this.IsPrivateToFile =
let isPrivate =
match this.Symbol with
| :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember || m.Accessibility.IsPrivate
| :? FSharpEntity as m -> m.Accessibility.IsPrivate
| :? FSharpGenericParameter -> true
| :? FSharpUnionCase as m -> m.Accessibility.IsPrivate
| :? FSharpField as m -> m.Accessibility.IsPrivate
| _ -> false
let declarationLocation =
match this.Symbol.SignatureLocation with
| Some x -> Some x
| _ ->
match this.Symbol.DeclarationLocation with
| Some x -> Some x
| _ -> this.Symbol.ImplementationLocation
let declaredInTheFile =
match declarationLocation with
| Some declRange -> declRange.FileName = this.RangeAlternate.FileName
| _ -> false
isPrivate && declaredInTheFile
type FSharpMemberOrFunctionOrValue with
member x.IsConstructor = x.CompiledName = ".ctor"
member x.IsOperatorOrActivePattern =
let name = x.DisplayName
if name.StartsWith "( " && name.EndsWith " )" && name.Length > 4
then name.Substring (2, name.Length - 4) |> String.forall (fun c -> c <> ' ')
else false
member x.EnclosingEntitySafe =
try
Some x.EnclosingEntity
with :? InvalidOperationException -> None
type FSharpEntity with
member x.AllBaseTypes =
let rec allBaseTypes (entity:FSharpEntity) =
[
match entity.TryFullName with
| Some _ ->
match entity.BaseType with
| Some bt ->
yield bt
if bt.HasTypeDefinition then
yield! allBaseTypes bt.TypeDefinition
| _ -> ()
| _ -> ()
]
allBaseTypes x
/// Active patterns over `FSharpSymbolUse`.
module SymbolUse =
let (|ActivePatternCase|_|) (symbol : FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpActivePatternCase as ap-> ActivePatternCase(ap) |> Some
| _ -> None
let private attributeSuffixLength = "Attribute".Length
let (|Entity|_|) (symbol : FSharpSymbolUse) : (FSharpEntity * (* cleanFullNames *) string list) option =
match symbol.Symbol with
| :? FSharpEntity as ent ->
// strip generic parameters count suffix (List`1 => List)
let cleanFullName =
// `TryFullName` for type aliases is always `None`, so we have to make one by our own
if ent.IsFSharpAbbreviation then
[ent.AccessPath + "." + ent.DisplayName]
else
ent.TryFullName
|> Option.toList
|> List.map (fun fullName ->
if ent.GenericParameters.Count > 0 && fullName.Length > 2 then
fullName.[0..fullName.Length - 3]
else fullName)
let cleanFullNames =
cleanFullName
|> List.collect (fun cleanFullName ->
if ent.IsAttributeType then
[cleanFullName; cleanFullName.[0..cleanFullName.Length - attributeSuffixLength - 1]]
else [cleanFullName]
)
Some (ent, cleanFullNames)
| _ -> None
let (|Field|_|) (symbol : FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpField as field-> Some field
| _ -> None
let (|GenericParameter|_|) (symbol: FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpGenericParameter as gp -> Some gp
| _ -> None
let (|MemberFunctionOrValue|_|) (symbol : FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpMemberOrFunctionOrValue as func -> Some func
| _ -> None
let (|ActivePattern|_|) = function
| MemberFunctionOrValue m when m.IsActivePattern -> Some m | _ -> None
let (|Parameter|_|) (symbol : FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpParameter as param -> Some param
| _ -> None
let (|StaticParameter|_|) (symbol : FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpStaticParameter as sp -> Some sp
| _ -> None
let (|UnionCase|_|) (symbol : FSharpSymbolUse) =
match symbol.Symbol with
| :? FSharpUnionCase as uc-> Some uc
| _ -> None
//let (|Constructor|_|) = function
// | MemberFunctionOrValue func when func.IsConstructor || func.IsImplicitConstructor -> Some func
// | _ -> None
let (|TypeAbbreviation|_|) = function
| Entity (entity, _) when entity.IsFSharpAbbreviation -> Some entity
| _ -> None
let (|Class|_|) = function
| Entity (entity, _) when entity.IsClass -> Some entity
| Entity (entity, _) when entity.IsFSharp &&
entity.IsOpaque &&
not entity.IsFSharpModule &&
not entity.IsNamespace &&
not entity.IsDelegate &&
not entity.IsFSharpUnion &&
not entity.IsFSharpRecord &&
not entity.IsInterface &&
not entity.IsValueType -> Some entity
| _ -> None
let (|Delegate|_|) = function
| Entity (entity, _) when entity.IsDelegate -> Some entity
| _ -> None
let (|Event|_|) = function
| MemberFunctionOrValue symbol when symbol.IsEvent -> Some symbol
| _ -> None
let (|Property|_|) = function
| MemberFunctionOrValue symbol when symbol.IsProperty || symbol.IsPropertyGetterMethod || symbol.IsPropertySetterMethod -> Some symbol
| _ -> None
let inline private notCtorOrProp (symbol:FSharpMemberOrFunctionOrValue) =
not symbol.IsConstructor && not symbol.IsPropertyGetterMethod && not symbol.IsPropertySetterMethod
let (|Method|_|) (symbolUse:FSharpSymbolUse) =
match symbolUse with
| MemberFunctionOrValue symbol when
symbol.IsModuleValueOrMember &&
not symbolUse.IsFromPattern &&
not symbol.IsOperatorOrActivePattern &&
not symbol.IsPropertyGetterMethod &&
not symbol.IsPropertySetterMethod -> Some symbol
| _ -> None
let (|Function|_|) (symbolUse:FSharpSymbolUse) =
match symbolUse with
| MemberFunctionOrValue symbol when
notCtorOrProp symbol &&
symbol.IsModuleValueOrMember &&
not symbol.IsOperatorOrActivePattern &&
not symbolUse.IsFromPattern ->
match symbol.FullTypeSafe with
| Some fullType when fullType.IsFunctionType -> Some symbol
| _ -> None
| _ -> None
let (|Operator|_|) (symbolUse:FSharpSymbolUse) =
match symbolUse with
| MemberFunctionOrValue symbol when
notCtorOrProp symbol &&
not symbolUse.IsFromPattern &&
not symbol.IsActivePattern &&
symbol.IsOperatorOrActivePattern ->
match symbol.FullTypeSafe with
| Some fullType when fullType.IsFunctionType -> Some symbol
| _ -> None
| _ -> None
let (|Pattern|_|) (symbolUse:FSharpSymbolUse) =
match symbolUse with
| MemberFunctionOrValue symbol when
notCtorOrProp symbol &&
not symbol.IsOperatorOrActivePattern &&
symbolUse.IsFromPattern ->
match symbol.FullTypeSafe with
| Some fullType when fullType.IsFunctionType ->Some symbol
| _ -> None
| _ -> None
let (|ClosureOrNestedFunction|_|) = function
| MemberFunctionOrValue symbol when
notCtorOrProp symbol &&
not symbol.IsOperatorOrActivePattern &&
not symbol.IsModuleValueOrMember ->
match symbol.FullTypeSafe with
| Some fullType when fullType.IsFunctionType -> Some symbol
| _ -> None
| _ -> None
let (|Val|_|) = function
| MemberFunctionOrValue symbol when notCtorOrProp symbol &&
not symbol.IsOperatorOrActivePattern ->
match symbol.FullTypeSafe with
| Some _fullType -> Some symbol
| _ -> None
| _ -> None
let (|Enum|_|) = function
| Entity (entity, _) when entity.IsEnum -> Some entity
| _ -> None
let (|Interface|_|) = function
| Entity (entity, _) when entity.IsInterface -> Some entity
| _ -> None
let (|Module|_|) = function
| Entity (entity, _) when entity.IsFSharpModule -> Some entity
| _ -> None
let (|Namespace|_|) = function
| Entity (entity, _) when entity.IsNamespace -> Some entity
| _ -> None
let (|Record|_|) = function
| Entity (entity, _) when entity.IsFSharpRecord -> Some entity
| _ -> None
let (|Union|_|) = function
| Entity (entity, _) when entity.IsFSharpUnion -> Some entity
| _ -> None
let (|ValueType|_|) = function
| Entity (entity, _) when entity.IsValueType && not entity.IsEnum -> Some entity
| _ -> None
let (|ComputationExpression|_|) (symbol:FSharpSymbolUse) =
if symbol.IsFromComputationExpression then Some symbol
else None
let (|Attribute|_|) = function
| Entity (entity, _) when entity.IsAttributeType -> Some entity
| _ -> None
\ No newline at end of file
module internal Microsoft.VisualStudio.FSharp.Editor.TypedAstUtils
open System
open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.SourceCodeServices
open Microsoft.VisualStudio.FSharp.Editor
open System.Text.RegularExpressions
let isAttribute<'T> (attribute: FSharpAttribute) =
// CompiledName throws exception on DataContractAttribute generated by SQLProvider
match Option.attempt (fun _ -> attribute.AttributeType.CompiledName) with
| Some name when name = typeof<'T>.Name -> true
| _ -> false
let tryGetAttribute<'T> (attributes: seq<FSharpAttribute>) =
attributes |> Seq.tryFind isAttribute<'T>
let hasModuleSuffixAttribute (entity: FSharpEntity) =
entity.Attributes
|> tryGetAttribute<CompilationRepresentationAttribute>
|> Option.bind (fun a ->
Option.attempt (fun _ -> a.ConstructorArguments)
|> Option.bind (fun args -> args |> Seq.tryPick (fun (_, arg) ->
let res =
match arg with
| :? int32 as arg when arg = int CompilationRepresentationFlags.ModuleSuffix ->
Some()
| :? CompilationRepresentationFlags as arg when arg = CompilationRepresentationFlags.ModuleSuffix ->
Some()
| _ ->
None
res)))
|> Option.isSome
let isOperator (name: string) =
name.StartsWith "( " && name.EndsWith " )" && name.Length > 4
&& name.Substring (2, name.Length - 4)
|> String.forall (fun c -> c <> ' ' && not (Char.IsLetter c))
let private UnnamedUnionFieldRegex = Regex("^Item(\d+)?$", RegexOptions.Compiled)
let isUnnamedUnionCaseField (field: FSharpField) = UnnamedUnionFieldRegex.IsMatch(field.Name)
module TypedAstPatterns =
let (|AbbreviatedType|_|) (entity: FSharpEntity) =
if entity.IsFSharpAbbreviation then Some entity.AbbreviatedType
else None
let (|TypeWithDefinition|_|) (ty: FSharpType) =
if ty.HasTypeDefinition then Some ty.TypeDefinition
else None
let rec getEntityAbbreviatedType (entity: FSharpEntity) =
if entity.IsFSharpAbbreviation then
match entity.AbbreviatedType with
| TypeWithDefinition def -> getEntityAbbreviatedType def
| abbreviatedType -> entity, Some abbreviatedType
else entity, None
let rec getAbbreviatedType (fsharpType: FSharpType) =
if fsharpType.IsAbbreviation then
getAbbreviatedType fsharpType.AbbreviatedType
else fsharpType
let (|Attribute|_|) (entity: FSharpEntity) =
let isAttribute (entity: FSharpEntity) =
let getBaseType (entity: FSharpEntity) =
try
match entity.BaseType with
| Some (TypeWithDefinition def) -> Some def
| _ -> None
with _ -> None
let rec isAttributeType (ty: FSharpEntity option) =
match ty with
| None -> false
| Some ty ->
match ty.TryGetFullName() with
| None -> false
| Some fullName ->
fullName = "System.Attribute" || isAttributeType (getBaseType ty)
isAttributeType (Some entity)
if isAttribute entity then Some() else None
let (|ValueType|_|) (e: FSharpEntity) =
if e.IsEnum || e.IsValueType || hasAttribute<MeasureAnnotatedAbbreviationAttribute> e.Attributes then Some()
else None
let (|Class|_|) (original: FSharpEntity, abbreviated: FSharpEntity, _) =
if abbreviated.IsClass
&& (not abbreviated.IsStaticInstantiation || original.IsFSharpAbbreviation) then Some()
else None
let (|Record|_|) (e: FSharpEntity) = if e.IsFSharpRecord then Some() else None
let (|UnionType|_|) (e: FSharpEntity) = if e.IsFSharpUnion then Some() else None
let (|Delegate|_|) (e: FSharpEntity) = if e.IsDelegate then Some() else None
let (|FSharpException|_|) (e: FSharpEntity) = if e.IsFSharpExceptionDeclaration then Some() else None
let (|Interface|_|) (e: FSharpEntity) = if e.IsInterface then Some() else None
let (|AbstractClass|_|) (e: FSharpEntity) =
if hasAttribute<AbstractClassAttribute> e.Attributes then Some() else None
let (|FSharpType|_|) (e: FSharpEntity) =
if e.IsDelegate || e.IsFSharpExceptionDeclaration || e.IsFSharpRecord || e.IsFSharpUnion
|| e.IsInterface || e.IsMeasure
|| (e.IsFSharp && e.IsOpaque && not e.IsFSharpModule && not e.IsNamespace) then Some()
else None
let (|ProvidedType|_|) (e: FSharpEntity) =
if (e.IsProvided || e.IsProvidedAndErased || e.IsProvidedAndGenerated) && e.CompiledName = e.DisplayName then
Some()
else None
let (|ByRef|_|) (e: FSharpEntity) = if e.IsByRef then Some() else None
let (|Array|_|) (e: FSharpEntity) = if e.IsArrayType then Some() else None
let (|FSharpModule|_|) (entity: FSharpEntity) = if entity.IsFSharpModule then Some() else None
let (|Namespace|_|) (entity: FSharpEntity) = if entity.IsNamespace then Some() else None
let (|ProvidedAndErasedType|_|) (entity: FSharpEntity) = if entity.IsProvidedAndErased then Some() else None
let (|Enum|_|) (entity: FSharpEntity) = if entity.IsEnum then Some() else None
let (|Tuple|_|) (ty: FSharpType option) =
ty |> Option.bind (fun ty -> if ty.IsTupleType then Some() else None)
let (|RefCell|_|) (ty: FSharpType) =
match getAbbreviatedType ty with
| TypeWithDefinition def when
def.IsFSharpRecord && def.FullName = "Microsoft.FSharp.Core.FSharpRef`1" -> Some()
| _ -> None
let (|FunctionType|_|) (ty: FSharpType) =
if ty.IsFunctionType then Some()
else None
let (|Pattern|_|) (symbol: FSharpSymbol) =
match symbol with
| :? FSharpUnionCase
| :? FSharpActivePatternCase -> Some()
| _ -> None
/// Field (field, fieldAbbreviatedType)
let (|Field|_|) (symbol: FSharpSymbol) =
match symbol with
| :? FSharpField as field -> Some (field, getAbbreviatedType field.FieldType)
| _ -> None
let (|MutableVar|_|) (symbol: FSharpSymbol) =
let isMutable =
match symbol with
| :? FSharpField as field -> field.IsMutable && not field.IsLiteral
| :? FSharpMemberOrFunctionOrValue as func -> func.IsMutable
| _ -> false
if isMutable then Some() else None
/// Entity (originalEntity, abbreviatedEntity, abbreviatedType)
let (|FSharpEntity|_|) (symbol: FSharpSymbol) =
match symbol with
| :? FSharpEntity as entity ->
let abbreviatedEntity, abbreviatedType = getEntityAbbreviatedType entity
Some (entity, abbreviatedEntity, abbreviatedType)
| _ -> None
let (|Parameter|_|) (symbol: FSharpSymbol) =
match symbol with
| :? FSharpParameter -> Some()
| _ -> None
let (|UnionCase|_|) (e: FSharpSymbol) =
match e with
| :? FSharpUnionCase as uc -> Some uc
| _ -> None
let (|RecordField|_|) (e: FSharpSymbol) =
match e with
| :? FSharpField as field ->
if field.DeclaringEntity.IsFSharpRecord then Some field else None
| _ -> None
let (|ActivePatternCase|_|) (symbol: FSharpSymbol) =
match symbol with
| :? FSharpActivePatternCase as case -> Some case
| _ -> None
/// Func (memberFunctionOrValue, fullType)
let (|MemberFunctionOrValue|_|) (symbol: FSharpSymbol) =
match symbol with
| :? FSharpMemberOrFunctionOrValue as func -> Some func
| _ -> None
/// Constructor (enclosingEntity)
let (|Constructor|_|) (func: FSharpMemberOrFunctionOrValue) =
match func.CompiledName with
| ".ctor" | ".cctor" -> Some func.EnclosingEntity
| _ -> None
let (|Function|_|) excluded (func: FSharpMemberOrFunctionOrValue) =
match func.FullTypeSafe |> Option.map getAbbreviatedType with
| Some typ when typ.IsFunctionType
&& not func.IsPropertyGetterMethod
&& not func.IsPropertySetterMethod
&& not excluded
&& not (isOperator func.DisplayName) -> Some()
| _ -> None
let (|ExtensionMember|_|) (func: FSharpMemberOrFunctionOrValue) =
if func.IsExtensionMember then Some() else None
let (|Event|_|) (func: FSharpMemberOrFunctionOrValue) =
if func.IsEvent then Some () else None
\ No newline at end of file
......@@ -15,7 +15,7 @@ open Microsoft.CodeAnalysis.FindUsages
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler.SourceCodeServices
[<ExportLanguageService(typeof<IFindUsagesService>, FSharpCommonConstants.FSharpLanguageName); Shared>]
[<ExportLanguageService(typeof<IFindUsagesService>, FSharpConstants.FSharpLanguageName); Shared>]
type internal FSharpFindUsagesService
[<ImportingConstructor>]
(
......@@ -34,9 +34,9 @@ type internal FSharpFindUsagesService
async {
let doc = solution.GetDocument(documentId)
let! sourceText = doc.GetTextAsync(cancellationToken)
match CommonRoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) with
match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) with
| Some span ->
let span = CommonHelpers.fixupSpan(sourceText, span)
let span = Tokenizer.fixupSpan(sourceText, span)
return Some (DocumentSpan(doc, span))
| None -> return None
})
......@@ -54,10 +54,10 @@ type internal FSharpFindUsagesService
let lineNumber = sourceText.Lines.GetLinePosition(position).Line + 1
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.FilePath, options.OtherOptions |> Seq.toList)
let! symbol = CommonHelpers.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! symbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let! symbolUse = checkFileResults.GetSymbolUseAtLocation(lineNumber, symbol.Ident.idRange.EndColumn, textLine, symbol.FullIsland)
let! declaration = checkFileResults.GetDeclarationLocationAlternate (lineNumber, symbol.Ident.idRange.EndColumn, textLine, symbol.FullIsland, false) |> liftAsync
let tags = GlyphTags.GetTags(CommonRoslynHelpers.GetGlyphForSymbol (symbolUse.Symbol, symbol.Kind))
let tags = GlyphTags.GetTags(Tokenizer.GetGlyphForSymbol (symbolUse.Symbol, symbol.Kind))
let declarationRange =
match declaration with
......@@ -142,8 +142,8 @@ type internal FSharpFindUsagesService
interface IFindUsagesService with
member __.FindReferencesAsync(document, position, context) =
findReferencedSymbolsAsync(document, position, context, true)
|> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
member __.FindImplementationsAsync(document, position, context) =
findReferencedSymbolsAsync(document, position, context, false)
|> CommonRoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
|> RoslynHelpers.StartAsyncUnitAsTask(context.CancellationToken)
\ No newline at end of file
......@@ -45,7 +45,7 @@ module internal FSharpGoToDefinition =
let textLine = sourceText.Lines.GetLineFromPosition position
let textLinePos = sourceText.Lines.GetLinePosition position
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! lexerSymbol = CommonHelpers.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let! _, _, checkFileResults =
checker.ParseAndCheckDocument
(filePath, textVersionHash, sourceText.ToString(), options, allowStaleResults = preferSignature)
......@@ -71,7 +71,7 @@ module internal FSharpGoToDefinition =
let refDocumentId = refDocumentIds.First()
let refDocument = document.Project.Solution.GetDocument refDocumentId
let! refSourceText = refDocument.GetTextAsync()
let refTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (refSourceText, range)
let refTextSpan = RoslynHelpers.FSharpRangeToTextSpan (refSourceText, range)
return Some (FSharpNavigableItem (refDocument, refTextSpan))
else return None
}
......@@ -83,12 +83,12 @@ module internal FSharpGoToDefinition =
let! projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject originDocument
let defines = CompilerEnvironment.GetCompilationDefinesForEditing (originDocument.FilePath, projectOptions.OtherOptions |> Seq.toList)
let originTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (sourceText, originRange)
let originTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sourceText, originRange)
let position = originTextSpan.Start
let! lexerSymbol =
CommonHelpers.getSymbolAtPosition
(originDocument.Id, sourceText, position, originDocument.FilePath, defines, SymbolLookupKind.Greedy)
Tokenizer.getSymbolAtPosition
(originDocument.Id, sourceText, position, originDocument.FilePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let textLinePos = sourceText.Lines.GetLinePosition position
let fcsTextLineNumber = Line.fromZ textLinePos.Line
......@@ -115,7 +115,7 @@ module internal FSharpGoToDefinition =
let! symbolUses = checkFileResults.GetUsesOfSymbolInFile symbol |> liftAsync
let! implSymbol = symbolUses |> Array.tryHead
let implTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (implSourceText, implSymbol.RangeAlternate)
let implTextSpan = RoslynHelpers.FSharpRangeToTextSpan (implSourceText, implSymbol.RangeAlternate)
return FSharpNavigableItem (implDoc, implTextSpan)
else
let! targetDocument = originDocument.Project.Solution.TryGetDocumentFromFSharpRange fsSymbolUse.RangeAlternate
......@@ -152,7 +152,7 @@ module internal FSharpGoToDefinition =
open FSharpGoToDefinition
[<Shared>]
[<ExportLanguageService (typeof<IGoToDefinitionService>, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportLanguageService (typeof<IGoToDefinitionService>, FSharpConstants.FSharpLanguageName)>]
[<Export (typeof<FSharpGoToDefinitionService>)>]
type internal FSharpGoToDefinitionService [<ImportingConstructor>]
(checkerProvider: FSharpCheckerProvider,
......@@ -253,7 +253,7 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
let textLine = sourceText.Lines.GetLineFromPosition position
let textLinePos = sourceText.Lines.GetLinePosition position
let fcsTextLineNumber = Line.fromZ textLinePos.Line
let! lexerSymbol = CommonHelpers.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(documentKey, sourceText, position, filePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let! _, _, checkFileResults =
checker.ParseAndCheckDocument
(filePath, textVersionHash, sourceText.ToString(), options, allowStaleResults = true) |> Async.RunSynchronously
......@@ -287,8 +287,8 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
checkerProvider.Checker.ParseAndCheckDocument (originDocument, projectOptions, allowStaleResults=true, sourceText=sourceText)
let! lexerSymbol =
CommonHelpers.getSymbolAtPosition
(originDocument.Id, sourceText, position,originDocument.FilePath, defines, SymbolLookupKind.Greedy)
Tokenizer.getSymbolAtPosition
(originDocument.Id, sourceText, position,originDocument.FilePath, defines, Tokenizer.SymbolLookupKind.Greedy)
let idRange = lexerSymbol.Ident.idRange
let! declarations =
......@@ -314,7 +314,7 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
findSymbolDeclarationInFile
(targetSymbolUse, implFilePath, implSourceText.ToString(), checkerProvider.Checker, projectOptions, implVersion.GetHashCode())
let implTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (implSourceText, targetRange)
let implTextSpan = RoslynHelpers.FSharpRangeToTextSpan (implSourceText, targetRange)
let navItem = FSharpNavigableItem (implDocument, implTextSpan)
results.Add navItem
return results.AsEnumerable()
......@@ -327,7 +327,7 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
| FSharpFindDeclResult.DeclFound targetRange ->
let! sigDocument = originDocument.Project.Solution.TryGetDocumentFromPath targetRange.FileName
let! sigSourceText = sigDocument.GetTextAsync () |> liftTaskAsync
let sigTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (sigSourceText, targetRange)
let sigTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sigSourceText, targetRange)
let navItem = FSharpNavigableItem (sigDocument, sigTextSpan)
results.Add navItem
return results.AsEnumerable()
......@@ -338,7 +338,7 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
else
let! sigDocument = originDocument.Project.Solution.TryGetDocumentFromPath targetRange.FileName
let! sigSourceText = sigDocument.GetTextAsync () |> liftTaskAsync
let sigTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (sigSourceText, targetRange)
let sigTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sigSourceText, targetRange)
// if the gotodef call originated from a signature and the returned target is a signature, navigate there
if isSignatureFile targetRange.FileName && preferSignature then
let navItem = FSharpNavigableItem (sigDocument, sigTextSpan)
......@@ -354,13 +354,13 @@ type internal FSharpGoToDefinitionService [<ImportingConstructor>]
let! targetRange =
findSymbolDeclarationInFile
(targetSymbolUse, implFilePath, implSourceText.ToString(), checkerProvider.Checker, projectOptions, implVersion.GetHashCode())
let implTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (implSourceText, targetRange)
let implTextSpan = RoslynHelpers.FSharpRangeToTextSpan (implSourceText, targetRange)
let navItem = FSharpNavigableItem (implDocument, implTextSpan)
results.Add navItem
return results.AsEnumerable()
| _ -> return! None
} |> Async.map (Option.defaultValue Seq.empty)
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
interface IGoToDefinitionService with
......
......@@ -177,7 +177,7 @@ module private Utils =
| _ -> container.Name
typeAsString + name
[<ExportLanguageService(typeof<INavigateToSearchService>, FSharpCommonConstants.FSharpLanguageName); Shared>]
[<ExportLanguageService(typeof<INavigateToSearchService>, FSharpConstants.FSharpLanguageName); Shared>]
type internal FSharpNavigateToSearchService
[<ImportingConstructor>]
(
......@@ -195,7 +195,7 @@ type internal FSharpNavigateToSearchService
match parseResults.ParseTree |> Option.map NavigateTo.getNavigableItems with
| Some items ->
[| for item in items do
let sourceSpan = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, item.Range)
let sourceSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, item.Range)
let glyph = Utils.navigateToItemKindToGlyph item.Kind
let kind = Utils.navigateToItemKindToRoslynKind item.Kind
let additionalInfo = Utils.containerToString item.Container document.Project
......@@ -257,7 +257,7 @@ type internal FSharpNavigateToSearchService
}
|> Async.map (Option.defaultValue [||])
|> Async.map Seq.toImmutableArray
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
member __.SearchDocumentAsync(document, searchPattern, cancellationToken) : Task<ImmutableArray<INavigateToSearchResult>> =
asyncMaybe {
......@@ -267,4 +267,4 @@ type internal FSharpNavigateToSearchService
}
|> Async.map (Option.defaultValue [||])
|> Async.map Seq.toImmutableArray
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
\ No newline at end of file
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
\ No newline at end of file
......@@ -18,7 +18,7 @@ open Microsoft.FSharp.Compiler.SourceCodeServices
type internal NavigationBarSymbolItem(text, glyph, spans, childItems) =
inherit NavigationBarItem(text, glyph, spans, childItems)
[<ExportLanguageService(typeof<INavigationBarItemService>, FSharpCommonConstants.FSharpLanguageName); Shared>]
[<ExportLanguageService(typeof<INavigationBarItemService>, FSharpConstants.FSharpLanguageName); Shared>]
type internal FSharpNavigationBarItemService
[<ImportingConstructor>]
(
......@@ -35,7 +35,7 @@ type internal FSharpNavigationBarItemService
let! sourceText = document.GetTextAsync(cancellationToken)
let! parsedInput = checkerProvider.Checker.ParseDocument(document, options, sourceText)
let navItems = NavigationImpl.getNavigation parsedInput
let rangeToTextSpan range = CommonRoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range)
let rangeToTextSpan range = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range)
return
navItems.Declarations
|> Array.choose (fun topLevelDecl ->
......@@ -52,7 +52,7 @@ type internal FSharpNavigationBarItemService
:> NavigationBarItem)) :> IList<_>
}
|> Async.map (Option.defaultValue emptyResult)
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
member __.ShowItemGrayedIfNear (_item) : bool = false
......
......@@ -19,6 +19,7 @@ open Microsoft.CodeAnalysis.Editor.Shared.Extensions
open Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo
open Microsoft.CodeAnalysis.Text
open Microsoft.VisualStudio.FSharp.LanguageService
open Microsoft.VisualStudio.Shell
open Microsoft.VisualStudio.Shell.Interop
......@@ -30,8 +31,9 @@ open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Compiler
open Internal.Utilities.StructuredFormat
open CommonRoslynHelpers
open Tokenizer
open System.Text
open RoslynHelpers
module private SessionHandling =
let mutable currentSession = None
......@@ -39,7 +41,7 @@ module private SessionHandling =
[<Export (typeof<IQuickInfoSourceProvider>)>]
[<Name (FSharpProviderConstants.SessionCapturingProvider)>]
[<Order (After = PredefinedQuickInfoProviderNames.Semantic)>]
[<ContentType (FSharpCommonConstants.FSharpContentTypeName)>]
[<ContentType (FSharpConstants.FSharpContentTypeName)>]
type SourceProviderForCapturingSession () =
interface IQuickInfoSourceProvider with
member x.TryCreateQuickInfoSource _ =
......@@ -99,7 +101,7 @@ module private FSharpQuickInfo =
let extDocument = solution.GetProject(extDocId.ProjectId).GetDocument extDocId
let! extSourceText = extDocument.GetTextAsync cancellationToken
let extSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (extSourceText, declRange)
let extSpan = RoslynHelpers.FSharpRangeToTextSpan (extSourceText, declRange)
let extLineText = (extSourceText.Lines.GetLineFromPosition extSpan.Start).ToString()
// project options need to be retrieved because the signature file could be in another project
......@@ -109,7 +111,7 @@ module private FSharpQuickInfo =
(extDocument.FilePath, extProjectOptions.OtherOptions |> Seq.toList)
let! extLexerSymbol =
CommonHelpers.getSymbolAtPosition
Tokenizer.getSymbolAtPosition
(extDocId, extSourceText, extSpan.Start, declRange.FileName, extDefines, SymbolLookupKind.Greedy)
let! _, _, extCheckFileResults =
......@@ -127,14 +129,14 @@ module private FSharpQuickInfo =
let! extSymbolUse =
extCheckFileResults.GetSymbolUseAtLocation(declRange.StartLine, extLexerSymbol.Ident.idRange.EndColumn, extLineText, extLexerSymbol.FullIsland)
let extTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (extSourceText, extLexerSymbol.Range)
let extTextSpan = RoslynHelpers.FSharpRangeToTextSpan (extSourceText, extLexerSymbol.Range)
return! Some (extTooltipText, extTextSpan, extSymbolUse, extLexerSymbol.Kind)
}
let! sourceText = document.GetTextAsync cancellationToken
let! projectOptions = projectInfoManager.TryGetOptionsForEditingDocumentOrProject document
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.FilePath, projectOptions.OtherOptions |> Seq.toList)
let! lexerSymbol = CommonHelpers.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let! lexerSymbol = Tokenizer.getSymbolAtPosition(document.Id, sourceText, position, document.FilePath, defines, SymbolLookupKind.Greedy)
let idRange = lexerSymbol.Ident.idRange
let! _, _, checkFileResults = checker.ParseAndCheckDocument(document, projectOptions, allowStaleResults = true, sourceText=sourceText)
let textLinePos = sourceText.Lines.GetLinePosition position
......@@ -153,7 +155,7 @@ module private FSharpQuickInfo =
| FSharpToolTipText [FSharpStructuredToolTipElement.None] -> return! None
| _ ->
let! symbolUse = checkFileResults.GetSymbolUseAtLocation (fcsTextLineNumber, idRange.EndColumn, lineText, lexerSymbol.FullIsland)
let targetTextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan (sourceText, lexerSymbol.Range)
let targetTextSpan = RoslynHelpers.FSharpRangeToTextSpan (sourceText, lexerSymbol.Range)
return! Some (targetTooltip, targetTextSpan, symbolUse, lexerSymbol.Kind)
}
......@@ -194,7 +196,7 @@ module private FSharpQuickInfo =
return (None, Some backupTooltipInfo)
}
[<ExportQuickInfoProvider(PredefinedQuickInfoProviderNames.Semantic, FSharpCommonConstants.FSharpLanguageName)>]
[<ExportQuickInfoProvider(PredefinedQuickInfoProviderNames.Semantic, FSharpConstants.FSharpLanguageName)>]
type internal FSharpQuickInfoProvider
[<System.ComponentModel.Composition.ImportingConstructor>]
(
......@@ -219,7 +221,7 @@ type internal FSharpQuickInfoProvider
let targetPath = range.FileName
let! targetDoc = solution.TryGetDocumentFromFSharpRange (range,initialDoc.Project.Id)
let! targetSource = targetDoc.GetTextAsync()
let! targetTextSpan = CommonRoslynHelpers.TryFSharpRangeToTextSpan (targetSource, range)
let! targetTextSpan = RoslynHelpers.TryFSharpRangeToTextSpan (targetSource, range)
// to ensure proper navigation decsions we need to check the type of document the navigation call
// is originating from and the target we're provided by default
// - signature files (.fsi) should navigate to other signature files
......@@ -284,14 +286,14 @@ type internal FSharpQuickInfoProvider
let textLine = sourceText.Lines.GetLineFromPosition position
let textLineNumber = textLine.LineNumber + 1 // Roslyn line numbers are zero-based
let defines = CompilerEnvironment.GetCompilationDefinesForEditing (filePath, options.OtherOptions |> Seq.toList)
let! symbol = CommonHelpers.getSymbolAtPosition (documentId, sourceText, position, filePath, defines, SymbolLookupKind.Precise)
let! symbol = Tokenizer.getSymbolAtPosition (documentId, sourceText, position, filePath, defines, SymbolLookupKind.Precise)
let! res = checkFileResults.GetStructuredToolTipTextAlternate (textLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland, FSharpTokenTag.IDENT) |> liftAsync
match res with
| FSharpToolTipText []
| FSharpToolTipText [FSharpStructuredToolTipElement.None] -> return! None
| _ ->
let! symbolUse = checkFileResults.GetSymbolUseAtLocation (textLineNumber, symbol.Ident.idRange.EndColumn, textLine.ToString(), symbol.FullIsland)
return! Some (res, CommonRoslynHelpers.FSharpRangeToTextSpan (sourceText, symbol.Range), symbolUse.Symbol, symbol.Kind)
return! Some (res, RoslynHelpers.FSharpRangeToTextSpan (sourceText, symbol.Range), symbolUse.Symbol, symbol.Kind)
}
interface IQuickInfoProvider with
......@@ -309,7 +311,7 @@ type internal FSharpQuickInfoProvider
XmlDocumentation.BuildDataTipText(documentationBuilder, mainDescription.Add, documentation.Add, toolTipElement)
let content =
FSharpQuickInfo.tooltip
(SymbolGlyphDeferredContent(CommonRoslynHelpers.GetGlyphForSymbol(symbolUse.Symbol, symbolKind), glyphService),
(SymbolGlyphDeferredContent(GetGlyphForSymbol(symbolUse.Symbol, symbolKind), glyphService),
fragment (mainDescription, typeMap, document, symbolUse.RangeAlternate),
fragment (documentation, typeMap, document, symbolUse.RangeAlternate))
return QuickInfoItem (textSpan, content)
......@@ -352,10 +354,10 @@ type internal FSharpQuickInfoProvider
let content =
FSharpQuickInfo.tooltip
(SymbolGlyphDeferredContent (CommonRoslynHelpers.GetGlyphForSymbol (targetSymbolUse.Symbol, targetSymbolKind), glyphService),
(SymbolGlyphDeferredContent (GetGlyphForSymbol (targetSymbolUse.Symbol, targetSymbolKind), glyphService),
fragment (description, typeMap, document, targetSymbolUse.RangeAlternate),
fragment (documentation, typeMap, document, targetSymbolUse.RangeAlternate))
return QuickInfoItem (targetTextSpan, content)
} |> Async.map Option.toObj
|> CommonRoslynHelpers.StartAsyncAsTask cancellationToken
|> RoslynHelpers.StartAsyncAsTask cancellationToken
......@@ -73,9 +73,9 @@ module internal BlockStructure =
|> Seq.distinctBy (fun x -> x.Range.StartLine)
|> Seq.choose (fun scopeRange ->
// the range of text to collapse
let textSpan = CommonRoslynHelpers.TryFSharpRangeToTextSpan(sourceText, scopeRange.CollapseRange)
let textSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, scopeRange.CollapseRange)
// the range of the entire expression
let hintSpan = CommonRoslynHelpers.TryFSharpRangeToTextSpan(sourceText, scopeRange.Range)
let hintSpan = RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, scopeRange.Range)
match textSpan,hintSpan with
| Some textSpan, Some hintSpan ->
let line = sourceText.Lines.GetLineFromPosition textSpan.Start
......@@ -93,7 +93,7 @@ open BlockStructure
type internal FSharpBlockStructureService(checker: FSharpChecker, projectInfoManager: ProjectInfoManager) =
inherit BlockStructureService()
override __.Language = FSharpCommonConstants.FSharpLanguageName
override __.Language = FSharpConstants.FSharpLanguageName
override __.GetBlockStructureAsync(document, cancellationToken) : Task<BlockStructure> =
asyncMaybe {
......@@ -104,9 +104,9 @@ type internal FSharpBlockStructureService(checker: FSharpChecker, projectInfoMan
}
|> Async.map (Option.defaultValue ImmutableArray<_>.Empty)
|> Async.map BlockStructure
|> CommonRoslynHelpers.StartAsyncAsTask(cancellationToken)
|> RoslynHelpers.StartAsyncAsTask(cancellationToken)
[<ExportLanguageServiceFactory(typeof<BlockStructureService>, FSharpCommonConstants.FSharpLanguageName); Shared>]
[<ExportLanguageServiceFactory(typeof<BlockStructureService>, FSharpConstants.FSharpLanguageName); Shared>]
type internal FSharpBlockStructureServiceFactory [<ImportingConstructor>](checkerProvider: FSharpCheckerProvider, projectInfoManager: ProjectInfoManager) =
interface ILanguageServiceFactory with
member __.CreateLanguageService(_languageServices) =
......
......@@ -731,7 +731,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem
override x.GetGuidProperty(propid:int, guid:byref<Guid> ) =
if (enum propid = __VSHPROPID.VSHPROPID_PreferredLanguageSID) then
guid <- new Guid(FSharpCommonConstants.languageServiceGuidString)
guid <- new Guid(FSharpConstants.languageServiceGuidString)
VSConstants.S_OK
// below is how VS decide 'which templates' to associate with an 'add new item' call in this project
elif (enum propid = __VSHPROPID2.VSHPROPID_AddItemTemplatesGuid) then
......@@ -1611,7 +1611,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem
// in the registry hive so that more editors can be added without changing this part of the
// code. FSharp only makes usage of one Editor Factory and therefore we will return
// that guid
guidEditorType <- new Guid(FSharpCommonConstants.editorFactoryGuidString)
guidEditorType <- new Guid(FSharpConstants.editorFactoryGuidString)
VSConstants.S_OK
interface IVsProjectSpecificEditorMap2 with
......@@ -1625,7 +1625,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem
// in the registry hive so that more editors can be added without changing this part of the
// code. FSharp only makes usage of one Editor Factory and therefore we will return
// that guid
guidEditorType <- new Guid(FSharpCommonConstants.editorFactoryGuidString)
guidEditorType <- new Guid(FSharpConstants.editorFactoryGuidString)
VSConstants.S_OK
member x.GetSpecificLanguageService(_mkDocument:string, guidLanguageService:byref<Guid> ) =
......
......@@ -147,9 +147,9 @@ type internal FSharpLanguageServiceTestable() as this =
match hier with
| :? IProvideProjectSite as siteProvider ->
let site = siteProvider.GetProjectSite()
site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName,
site.AdviseProjectSiteChanges(FSharpConstants.FSharpLanguageServiceCallbackName,
new AdviseProjectSiteChanges(fun () -> this.OnProjectSettingsChanged(site)))
site.AdviseProjectSiteCleaned(FSharpCommonConstants.FSharpLanguageServiceCallbackName,
site.AdviseProjectSiteCleaned(FSharpConstants.FSharpLanguageServiceCallbackName,
new AdviseProjectSiteChanges(fun () -> this.OnProjectCleaned(site)))
| _ ->
// This can happen when the file is in a solution folder or in, say, a C# project.
......
......@@ -50,7 +50,7 @@ type BraceMatchingServiceTests() =
| None -> Assert.Fail("Didn't find a match for start brace at position '{0}", startMarkerPosition)
| Some(left, right) ->
let endPositionInRange(range) =
let span = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range)
let span = RoslynHelpers.FSharpRangeToTextSpan(sourceText, range)
span.Start <= endMarkerPosition && endMarkerPosition <= span.End
Assert.IsTrue(endPositionInRange(left) || endPositionInRange(right), "Found end match at incorrect position")
......
......@@ -76,7 +76,7 @@ let main argv =
match actualResolutionOption with
| None -> Assert.IsTrue(expectedResolution.IsNone, "BreakpointResolutionService failed to resolve breakpoint position")
| Some(actualResolutionRange) ->
let actualResolution = sourceText.GetSubText(CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, actualResolutionRange)).ToString()
let actualResolution = sourceText.GetSubText(RoslynHelpers.FSharpRangeToTextSpan(sourceText, actualResolutionRange)).ToString()
Assert.IsTrue(expectedResolution.IsSome, "BreakpointResolutionService resolved a breakpoint while it shouldn't at: {0}", actualResolution)
Assert.AreEqual(expectedResolution.Value, actualResolution, "Expected and actual resolutions should match")
\ No newline at end of file
......@@ -10,6 +10,7 @@ open Microsoft.CodeAnalysis.Classification
open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Text
open Microsoft.VisualStudio.FSharp.Editor
open RoslynHelpers
[<TestFixture>][<Category "Roslyn Services">]
type ColorizationServiceTests() =
......@@ -18,7 +19,7 @@ type ColorizationServiceTests() =
let textSpan = TextSpan(0, fileContents.Length)
let fileName = if isScriptFile.IsSome && isScriptFile.Value then "test.fsx" else "test.fs"
let documentId = DocumentId.CreateNewId(ProjectId.CreateNewId())
let tokens = CommonHelpers.getColorizationData(documentId, SourceText.From(fileContents), textSpan, Some(fileName), defines, CancellationToken.None)
let tokens = Tokenizer.getColorizationData(documentId, SourceText.From(fileContents), textSpan, Some(fileName), defines, CancellationToken.None)
let markerPosition = fileContents.IndexOf(marker)
Assert.IsTrue(markerPosition >= 0, "Cannot find marker '{0}' in file contents", marker)
(tokens, markerPosition)
......
......@@ -58,7 +58,7 @@ let private getSpans (sourceText: SourceText) (caretPosition: int) =
let private span sourceText isDefinition (startLine, startCol) (endLine, endCol) =
let range = Range.mkRange filePath (Range.mkPos startLine startCol) (Range.mkPos endLine endCol)
{ IsDefinition = isDefinition
TextSpan = CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range) }
TextSpan = RoslynHelpers.FSharpRangeToTextSpan(sourceText, range) }
[<Test>]
let ShouldHighlightAllSimpleLocalSymbolReferences() =
......
......@@ -58,7 +58,7 @@ type HelpContextServiceTests() =
let span = TextSpan(marker, 0)
let textLine = sourceText.Lines.GetLineFromPosition(marker)
let documentId = DocumentId.CreateNewId(ProjectId.CreateNewId())
let tokens = CommonHelpers.getColorizationData(documentId, sourceText, textLine.Span, Some "test.fs", [], CancellationToken.None)
let tokens = Tokenizer.getColorizationData(documentId, sourceText, textLine.Span, Some "test.fs", [], CancellationToken.None)
yield FSharpHelpContextService.GetHelpTerm(FSharpChecker.Instance, sourceText, fileName, newOptions, span, tokens, version)
|> Async.RunSynchronously
......
......@@ -54,7 +54,7 @@ let main argv =
let sourceText = SourceText.From(code)
let documentId = DocumentId.CreateNewId(ProjectId.CreateNewId())
let tokens = CommonHelpers.getColorizationData(documentId, sourceText, TextSpan.FromBounds(0, sourceText.Length), Some(fileName), defines, CancellationToken.None)
let tokens = Tokenizer.getColorizationData(documentId, sourceText, TextSpan.FromBounds(0, sourceText.Length), Some(fileName), defines, CancellationToken.None)
let actualDataTipSpanOption = FSharpLanguageDebugInfoService.GetDataTipInformation(sourceText, searchPosition, tokens)
match actualDataTipSpanOption with
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册