Skip to content

Commit e10e878

Browse files
author
Omar Tawfik
committed
Use project options from project site
1 parent c0a3f89 commit e10e878

File tree

8 files changed

+62
-80
lines changed

8 files changed

+62
-80
lines changed

vsintegration/src/FSharp.Editor/BraceMatchingService.fs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@ type internal FSharpBraceMatchingService() =
2323
interface IBraceMatcher with
2424
member this.FindBracesAsync(document, position, cancellationToken) =
2525
let computation = async {
26-
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
27-
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
28-
let! result = FSharpBraceMatchingService.GetBraceMatchingResult(sourceText, document.Name, options, position)
29-
30-
return match result with
31-
| None -> Nullable()
32-
| Some(left, right) ->
33-
Nullable(BraceMatchingResult(
34-
CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, left),
35-
CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, right)))
26+
match FSharpLanguageService.GetOptions(document.Project.Id) with
27+
| Some(options) ->
28+
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
29+
let! result = FSharpBraceMatchingService.GetBraceMatchingResult(sourceText, document.Name, options, position)
30+
return match result with
31+
| None -> Nullable()
32+
| Some(left, right) ->
33+
Nullable(BraceMatchingResult(
34+
CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, left),
35+
CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, right)))
36+
| None -> return Nullable()
3637
}
3738

3839
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)

vsintegration/src/FSharp.Editor/BreakpointResolutionService.fs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ type internal FSharpBreakpointResolutionService() =
4444
interface IBreakpointResolutionService with
4545
member this.ResolveBreakpointAsync(document: Document, textSpan: TextSpan, cancellationToken: CancellationToken): Task<BreakpointResolutionResult> =
4646
let computation = async {
47-
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
48-
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
49-
let! location = FSharpBreakpointResolutionService.GetBreakpointLocation(sourceText, document.Name, textSpan, options)
50-
51-
return match location with
52-
| None -> null
53-
| Some(range) -> BreakpointResolutionResult.CreateSpanResult(document, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
47+
match FSharpLanguageService.GetOptions(document.Project.Id) with
48+
| Some(options) ->
49+
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
50+
let! location = FSharpBreakpointResolutionService.GetBreakpointLocation(sourceText, document.Name, textSpan, options)
51+
return match location with
52+
| None -> null
53+
| Some(range) -> BreakpointResolutionResult.CreateSpanResult(document, CommonRoslynHelpers.FSharpRangeToTextSpan(sourceText, range))
54+
| None -> return null
5455
}
5556

5657
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)

vsintegration/src/FSharp.Editor/ColorizationService.fs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,18 @@ type internal FSharpColorizationService() =
130130

131131
interface IEditorClassificationService with
132132

133-
member this.AddLexicalClassifications(text: SourceText, textSpan: TextSpan, result: List<ClassifiedSpan>, cancellationToken: CancellationToken) =
134-
result.AddRange(FSharpColorizationService.GetColorizationData(text, textSpan, None, [], cancellationToken))
133+
// Do not perform classification if we don't have project options (#defines matter)
134+
member this.AddLexicalClassifications(_: SourceText, _: TextSpan, _: List<ClassifiedSpan>, _: CancellationToken) = ()
135135

136136
member this.AddSyntacticClassificationsAsync(document: Document, textSpan: TextSpan, result: List<ClassifiedSpan>, cancellationToken: CancellationToken) =
137137
document.GetTextAsync(cancellationToken).ContinueWith(
138138
fun (sourceTextTask: Task<SourceText>) ->
139-
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
140-
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, options.OtherOptions |> Seq.toList)
141-
142-
if sourceTextTask.Status = TaskStatus.RanToCompletion then
143-
result.AddRange(FSharpColorizationService.GetColorizationData(sourceTextTask.Result, textSpan, None, defines, cancellationToken))
139+
match FSharpLanguageService.GetOptions(document.Project.Id) with
140+
| Some(options) ->
141+
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, options.OtherOptions |> Seq.toList)
142+
if sourceTextTask.Status = TaskStatus.RanToCompletion then
143+
result.AddRange(FSharpColorizationService.GetColorizationData(sourceTextTask.Result, textSpan, None, defines, cancellationToken))
144+
| None -> ()
144145
, cancellationToken)
145146

146147
// FSROSLYNTODO: Due to issue 12732 on Roslyn side, semantic classification is tied to C#/VB only.
@@ -168,10 +169,6 @@ type internal FSharpColorizationService() =
168169
Task.Run(fun () -> Async.RunSynchronously(computation, cancellationToken = cancellationToken))
169170
*)
170171
Task.CompletedTask
171-
172-
member this.AdjustStaleClassification(text: SourceText, classifiedSpan: ClassifiedSpan) : ClassifiedSpan =
173-
let tokens = FSharpColorizationService.GetColorizationData(text, classifiedSpan.TextSpan, None, [], CancellationToken.None)
174-
if tokens.Any() then
175-
tokens.First()
176-
else
177-
new ClassifiedSpan(ClassificationTypeNames.WhiteSpace, classifiedSpan.TextSpan)
172+
173+
// Do not perform classification if we don't have project options (#defines matter)
174+
member this.AdjustStaleClassification(_: SourceText, classifiedSpan: ClassifiedSpan) : ClassifiedSpan = classifiedSpan

vsintegration/src/FSharp.Editor/CommonRoslynHelpers.fs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,6 @@ open Microsoft.VisualStudio.FSharp.LanguageService
1212

1313
module internal CommonRoslynHelpers =
1414

15-
// Create F# project options for a Roslyn project.
16-
let rec GetFSharpProjectOptionsForRoslynProject(project: Project) : FSharpProjectOptions = {
17-
ProjectFileName = project.FilePath
18-
ProjectFileNames = project.Documents
19-
|> Seq.map (fun document -> document.Name)
20-
|> Seq.toArray
21-
ReferencedProjects = project.ProjectReferences
22-
|> Seq.map(fun reference -> project.Solution.Projects |> Seq.find(fun otherProject -> otherProject.Id = reference.ProjectId))
23-
|> Seq.map(fun otherProject -> (otherProject.FilePath, GetFSharpProjectOptionsForRoslynProject(otherProject)))
24-
|> Seq.toArray
25-
26-
// FSROSLYNTODO: add defines flags if available from project sites and files
27-
OtherOptions = [| |]
28-
29-
IsIncompleteTypeCheckEnvironment = true
30-
UseScriptResolutionRules = false
31-
LoadTime = DateTime.MaxValue
32-
UnresolvedReferences = None
33-
}
34-
3515
let FSharpRangeToTextSpan(sourceText: SourceText, range: range) =
3616
// Roslyn TextLineCollection is zero-based, F# range lines are one-based
3717
let startPosition = sourceText.Lines.[range.StartLine - 1].Start + range.StartColumn

vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
6262

6363
override this.AnalyzeSyntaxAsync(document: Document, cancellationToken: CancellationToken): Task<ImmutableArray<Diagnostic>> =
6464
let computation = async {
65-
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
66-
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
67-
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, options, false)
65+
match FSharpLanguageService.GetOptions(document.Project.Id) with
66+
| Some(options) ->
67+
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
68+
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, options, false)
69+
| None -> return ImmutableArray<Diagnostic>.Empty
6870
}
6971

7072
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)
@@ -73,9 +75,11 @@ type internal FSharpDocumentDiagnosticAnalyzer() =
7375

7476
override this.AnalyzeSemanticsAsync(document: Document, cancellationToken: CancellationToken): Task<ImmutableArray<Diagnostic>> =
7577
let computation = async {
76-
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
77-
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
78-
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, options, true)
78+
match FSharpLanguageService.GetOptions(document.Project.Id) with
79+
| Some(options) ->
80+
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
81+
return FSharpDocumentDiagnosticAnalyzer.GetDiagnostics(document.FilePath, sourceText, options, true)
82+
| None -> return ImmutableArray<Diagnostic>.Empty
7983
}
8084

8185
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)

vsintegration/src/FSharp.Editor/LanguageDebugInfoService.fs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ type internal FSharpLanguageDebugInfoService() =
6363

6464
member this.GetDataTipInfoAsync(document: Document, position: int, cancellationToken: CancellationToken): Task<DebugDataTipInfo> =
6565
let computation = async {
66-
let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project)
67-
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, options.OtherOptions |> Seq.toList)
68-
69-
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
70-
let textSpan = TextSpan.FromBounds(0, sourceText.Length)
71-
let tokens = FSharpColorizationService.GetColorizationData(sourceText, textSpan, Some(document.Name), defines, cancellationToken)
72-
73-
return match FSharpLanguageDebugInfoService.GetDataTipInformation(sourceText, position, tokens) with
74-
| None -> Unchecked.defaultof<DebugDataTipInfo>
75-
| Some(textSpan) -> new DebugDataTipInfo(textSpan, sourceText.GetSubText(textSpan).ToString())
66+
match FSharpLanguageService.GetOptions(document.Project.Id) with
67+
| Some(options) ->
68+
let defines = CompilerEnvironment.GetCompilationDefinesForEditing(document.Name, options.OtherOptions |> Seq.toList)
69+
let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask
70+
let textSpan = TextSpan.FromBounds(0, sourceText.Length)
71+
let tokens = FSharpColorizationService.GetColorizationData(sourceText, textSpan, Some(document.Name), defines, cancellationToken)
72+
return match FSharpLanguageDebugInfoService.GetDataTipInformation(sourceText, position, tokens) with
73+
| None -> Unchecked.defaultof<DebugDataTipInfo>
74+
| Some(textSpan) -> new DebugDataTipInfo(textSpan, sourceText.GetSubText(textSpan).ToString())
75+
| None -> return Unchecked.defaultof<DebugDataTipInfo>
7676
}
7777

7878
Async.StartAsTask(computation, TaskCreationOptions.None, cancellationToken)

vsintegration/src/FSharp.Editor/LanguageService.fs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ type internal SVsSettingsPersistenceManager = class end
2929
type internal FSharpLanguageService(package : FSharpPackage) =
3030
inherit AbstractLanguageService<FSharpPackage, FSharpLanguageService, FSharpProjectSite>(package)
3131

32+
static let optionsCache = Dictionary<ProjectId, FSharpProjectOptions>()
33+
static member GetOptions(projectId: ProjectId) =
34+
if optionsCache.ContainsKey(projectId) then
35+
Some(optionsCache.[projectId])
36+
else
37+
None
38+
3239
override this.ContentTypeName = FSharpCommonConstants.FSharpContentTypeName
3340
override this.LanguageName = FSharpCommonConstants.FSharpLanguageName
3441
override this.RoslynLanguageName = FSharpCommonConstants.FSharpLanguageName
@@ -56,6 +63,11 @@ type internal FSharpLanguageService(package : FSharpPackage) =
5663
let site = siteProvider.GetProjectSite()
5764
let projectFileName = site.ProjectFileName()
5865
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectFileName)
66+
67+
let options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName())
68+
if not (optionsCache.ContainsKey(projectId)) then
69+
optionsCache.Add(projectId, options)
70+
5971
if obj.ReferenceEquals(workspace.ProjectTracker.GetProject(projectId), null) then
6072
let projectSite = new FSharpProjectSite(hier, this.SystemServiceProvider, workspace, projectFileName);
6173
projectSite.Initialize(hier, site)

vsintegration/src/FSharp.Editor/ProjectSite.fs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
2121
type internal FSharpProjectSite(hierarchy: IVsHierarchy, serviceProvider: System.IServiceProvider, visualStudioWorkspace: VisualStudioWorkspaceImpl, projectName: string) =
2222
inherit AbstractProject(visualStudioWorkspace.ProjectTracker, null, projectName, hierarchy, FSharpCommonConstants.FSharpLanguageName, serviceProvider, visualStudioWorkspace, null)
2323

24-
let mutable checkOptions : FSharpProjectOptions option = None
25-
26-
member internal this.CheckOptions =
27-
match checkOptions with
28-
| Some options -> options
29-
| None -> failwith "Options haven't been computed yet."
30-
3124
member internal this.Initialize(hier: IVsHierarchy, site : IProjectSite) =
3225
this.ProjectTracker.AddProject(this)
3326

@@ -40,9 +33,6 @@ type internal FSharpProjectSite(hierarchy: IVsHierarchy, serviceProvider: System
4033
// Add files and references
4134
for file in site.SourceFilesOnDisk() do this.AddDocument(hier, file)
4235
for ref in this.GetReferences(site.CompilerFlags()) do this.AddReference(ref)
43-
44-
// Capture the F# specific options that we'll pass to the type checker.
45-
checkOptions <- Some(ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName()))
4636

4737
member this.GetReferences(flags : string[]) =
4838
flags |> Array.choose(fun flag -> if flag.StartsWith("-r:") then Some(flag.Substring(3)) else None)
@@ -77,6 +67,3 @@ type internal FSharpProjectSite(hierarchy: IVsHierarchy, serviceProvider: System
7767
for ref in references do if not(this.HasMetadataReference(ref)) then this.AddReference(ref)
7868
// Removed references
7969
for ref in this.GetCurrentMetadataReferences() do if not(references |> Seq.contains(ref.FilePath)) then this.RemoveReference(ref.FilePath)
80-
81-
// If the order of files changed, that'll be captured in the checkOptions.
82-
checkOptions <- Some(ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName()))

0 commit comments

Comments
 (0)