Skip to content

Commit

Permalink
Merge branch 'master' into navigate-to
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinRansom authored Dec 16, 2016
2 parents 34aed70 + 7593a6d commit c906bad
Show file tree
Hide file tree
Showing 7 changed files with 426 additions and 22 deletions.
139 changes: 123 additions & 16 deletions CommonHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ module CommonHelpers =
| FSharpTokenColorKind.PreprocessorKeyword -> ClassificationTypeNames.PreprocessorKeyword
| FSharpTokenColorKind.Operator -> ClassificationTypeNames.Operator
| FSharpTokenColorKind.TypeName -> ClassificationTypeNames.ClassName
| FSharpTokenColorKind.Default
| FSharpTokenColorKind.Default
| _ -> ClassificationTypeNames.Text

let private scanSourceLine(sourceTokenizer: FSharpSourceTokenizer, textLine: TextLine, lineContents: string, lexState: FSharpTokenizerLexState) : SourceLineData =
Expand All @@ -71,11 +71,7 @@ module CommonHelpers =
let tokenInfoOption, nextLexState = lineTokenizer.ScanToken(lexState.Value)
lexState.Value <- nextLexState
if tokenInfoOption.IsSome then
let classificationType =
if tokenInfoOption.Value.CharClass = FSharpTokenCharKind.WhiteSpace then
ClassificationTypeNames.WhiteSpace
else
compilerTokenToRoslynToken(tokenInfoOption.Value.ColorClass)
let classificationType = compilerTokenToRoslynToken(tokenInfoOption.Value.ColorClass)
for i = tokenInfoOption.Value.LeftColumn to tokenInfoOption.Value.RightColumn do
Array.set colorMap i classificationType
tokenInfoOption
Expand Down Expand Up @@ -163,21 +159,14 @@ module CommonHelpers =
Assert.Exception(ex)
List<ClassifiedSpan>()

let tryClassifyAtPosition (documentKey, sourceText: SourceText, filePath, defines, position: int, includeRightColumn: bool, cancellationToken) =
let tryClassifyAtPosition (documentKey, sourceText: SourceText, filePath, defines, position: int, cancellationToken) =
let textLine = sourceText.Lines.GetLineFromPosition(position)
let textLinePos = sourceText.Lines.GetLinePosition(position)
let textLineColumn = textLinePos.Character

let classifiedSpanOption =
getColorizationData(documentKey, sourceText, textLine.Span, Some(filePath), defines, cancellationToken)
|> Seq.tryFind(fun classifiedSpan ->
if includeRightColumn then
classifiedSpan.ClassificationType <> ClassificationTypeNames.WhiteSpace &&
(classifiedSpan.TextSpan.Contains(position) ||
// TextSpan.Contains returns `false` for `position` equals its right bound,
// so we have to check if it contains `position - 1`.
(position > 0 && classifiedSpan.TextSpan.Contains(position - 1)))
else classifiedSpan.TextSpan.Contains(position))
|> Seq.tryFind(fun classifiedSpan -> classifiedSpan.TextSpan.Contains(position))

match classifiedSpanOption with
| Some(classifiedSpan) ->
Expand All @@ -201,6 +190,123 @@ module CommonHelpers =
| _ -> None
| _ -> None

/// Fix invalid span if it appears to have redundant suffix and prefix.
let fixupSpan (sourceText: SourceText, span: TextSpan) : TextSpan =
let text = sourceText.GetSubText(span).ToString()
match text.LastIndexOf '.' with
| -1 | 0 -> span
| index -> TextSpan(span.Start + index + 1, text.Length - index - 1)

let glyphMajorToRoslynGlyph = function
| GlyphMajor.Class
| GlyphMajor.Typedef
| GlyphMajor.Type
| GlyphMajor.Exception -> Glyph.ClassPublic
| GlyphMajor.Constant -> Glyph.ConstantPublic
| GlyphMajor.Delegate -> Glyph.DelegatePublic
| GlyphMajor.Union
| GlyphMajor.Enum -> Glyph.EnumPublic
| GlyphMajor.EnumMember
| GlyphMajor.Variable
| GlyphMajor.FieldBlue -> Glyph.FieldPublic
| GlyphMajor.Event -> Glyph.EventPublic
| GlyphMajor.Interface -> Glyph.InterfacePublic
| GlyphMajor.Method
| GlyphMajor.Method2 -> Glyph.MethodPublic
| GlyphMajor.Module -> Glyph.ModulePublic
| GlyphMajor.NameSpace -> Glyph.Namespace
| GlyphMajor.Property -> Glyph.PropertyPublic
| GlyphMajor.Struct
| GlyphMajor.ValueType -> Glyph.StructurePublic
| GlyphMajor.Error -> Glyph.Error
| _ -> Glyph.None

[<RequireQualifiedAccess; NoComparison>]
type internal SymbolDeclarationLocation =
| CurrentDocument
| Projects of Project list * isLocalForProject: bool

[<AutoOpen>]
module internal Extensions =
open System
open System.IO

type Path with
static member GetFullPathSafe path =
try Path.GetFullPath path
with _ -> path

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 = String.Equals(Path.GetExtension(filePath), ".fsx", StringComparison.OrdinalIgnoreCase)
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(currentDocument.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
| :? 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

let glyphMajorToRoslynGlyph = function
| GlyphMajor.Class -> Glyph.ClassPublic
| GlyphMajor.Constant -> Glyph.ConstantPublic
Expand All @@ -223,4 +329,5 @@ module CommonHelpers =
| GlyphMajor.Variable -> Glyph.FieldPublic
| GlyphMajor.ValueType -> Glyph.StructurePublic
| GlyphMajor.Error -> Glyph.Error
| _ -> Glyph.None
| _ -> Glyph.None

15 changes: 15 additions & 0 deletions CommonRoslynHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ module internal CommonRoslynHelpers =
let endPosition = sourceText.Lines.[range.EndLine - 1].Start + range.EndColumn
TextSpan(startPosition, endPosition - startPosition)

let TryFSharpRangeToTextSpan(sourceText: SourceText, range: range) : TextSpan option =
try Some(FSharpRangeToTextSpan(sourceText, range))
with e ->
//Assert.Exception(e)
None

let GetCompletedTaskResult(task: Task<'TResult>) =
if task.Status = TaskStatus.RanToCompletion then
task.Result
Expand Down Expand Up @@ -53,3 +59,12 @@ module internal CommonRoslynHelpers =
let severity = if error.Severity = FSharpErrorSeverity.Error then DiagnosticSeverity.Error else DiagnosticSeverity.Warning
let descriptor = new DiagnosticDescriptor(id, emptyString, description, error.Subcategory, severity, true, emptyString, String.Empty, null)
Diagnostic.Create(descriptor, location)

[<AutoOpen>]
module internal RoslynExtensions =
type Project with
/// The list of all other projects within the same solution that reference this project.
member this.GetDependentProjects() =
[ for project in this.Solution.Projects do
if project.ProjectReferences |> Seq.exists (fun ref -> ref.ProjectId = this.Id) then
yield project ]
5 changes: 2 additions & 3 deletions FSharp.Editor.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
Expand All @@ -18,8 +18,7 @@
<TargetType>LIBRARY</TargetType>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<NoWarn>$(NoWarn);75</NoWarn>
<Tailcalls Condition="'$(CodeCoverage)' != ''">false</Tailcalls>
<OtherFlags>$(OtherFlags) --warnon:1182 --subsystemversion:6.00</OtherFlags>
<Tailcalls Condition="'$(CodeCoverage)' != ''">false</Tailcalls> <OtherFlags>$(OtherFlags) --warnon:1182 --subsystemversion:6.00</OtherFlags>
<ImportVSSDKTargets>true</ImportVSSDKTargets>
<CreateVsixContainer>false</CreateVsixContainer>
<DeployExtension>false</DeployExtension>
Expand Down
Loading

0 comments on commit c906bad

Please sign in to comment.