diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config index 2210fd599b7..16b3affadcf 100644 --- a/.nuget/NuGet.Config +++ b/.nuget/NuGet.Config @@ -8,7 +8,7 @@ - + diff --git a/packages.config b/packages.config index 5d2b3e4e9d1..78eeeb715c8 100644 --- a/packages.config +++ b/packages.config @@ -18,12 +18,12 @@ - - - - - - + + + + + + diff --git a/src/FSharpSource.Settings.targets b/src/FSharpSource.Settings.targets index 5e2854dea30..f4149e250f2 100644 --- a/src/FSharpSource.Settings.targets +++ b/src/FSharpSource.Settings.targets @@ -90,7 +90,7 @@ fsi.exe fslex.exe fsyacc.exe - 2.0.0-beta4-60808-03 + 2.0.0-beta6-61005-05 14.0 14.3.25407 diff --git a/vsintegration/src/FSharp.Editor/ColorizationService.fs b/vsintegration/src/FSharp.Editor/ColorizationService.fs index 7a2610613e9..1ab24a9d0a0 100644 --- a/vsintegration/src/FSharp.Editor/ColorizationService.fs +++ b/vsintegration/src/FSharp.Editor/ColorizationService.fs @@ -37,26 +37,26 @@ type private SourceTextData(lines: int) = type internal FSharpColorizationService() = static let DataCache = ConditionalWeakTable() + + static let compilerTokenToRoslynToken(colorKind: FSharpTokenColorKind) : string = + match colorKind with + | FSharpTokenColorKind.Comment -> ClassificationTypeNames.Comment + | FSharpTokenColorKind.Identifier -> ClassificationTypeNames.Identifier + | FSharpTokenColorKind.Keyword -> ClassificationTypeNames.Keyword + | FSharpTokenColorKind.String -> ClassificationTypeNames.StringLiteral + | FSharpTokenColorKind.Text -> ClassificationTypeNames.Text + | FSharpTokenColorKind.UpperIdentifier -> ClassificationTypeNames.Identifier + | FSharpTokenColorKind.Number -> ClassificationTypeNames.NumericLiteral + | FSharpTokenColorKind.InactiveCode -> ClassificationTypeNames.ExcludedCode + | FSharpTokenColorKind.PreprocessorKeyword -> ClassificationTypeNames.PreprocessorKeyword + | FSharpTokenColorKind.Operator -> ClassificationTypeNames.Operator + | FSharpTokenColorKind.TypeName -> ClassificationTypeNames.ClassName + | FSharpTokenColorKind.Default | _ -> ClassificationTypeNames.Text static let scanSourceLine(sourceTokenizer: FSharpSourceTokenizer, textLine: TextLine, lineContents: string, lexState: FSharpTokenizerLexState) : SourceLineData = let colorMap = Array.create textLine.Span.Length ClassificationTypeNames.Text let lineTokenizer = sourceTokenizer.CreateLineTokenizer(lineContents) - - let compilerTokenToRoslynToken(colorKind: FSharpTokenColorKind) : string = - match colorKind with - | FSharpTokenColorKind.Comment -> ClassificationTypeNames.Comment - | FSharpTokenColorKind.Identifier -> ClassificationTypeNames.Identifier - | FSharpTokenColorKind.Keyword -> ClassificationTypeNames.Keyword - | FSharpTokenColorKind.String -> ClassificationTypeNames.StringLiteral - | FSharpTokenColorKind.Text -> ClassificationTypeNames.Text - | FSharpTokenColorKind.UpperIdentifier -> ClassificationTypeNames.Identifier - | FSharpTokenColorKind.Number -> ClassificationTypeNames.NumericLiteral - | FSharpTokenColorKind.InactiveCode -> ClassificationTypeNames.ExcludedCode - | FSharpTokenColorKind.PreprocessorKeyword -> ClassificationTypeNames.PreprocessorKeyword - | FSharpTokenColorKind.Operator -> ClassificationTypeNames.Operator - | FSharpTokenColorKind.TypeName -> ClassificationTypeNames.ClassName - | FSharpTokenColorKind.Default | _ -> ClassificationTypeNames.Text let scanAndColorNextToken(lineTokenizer: FSharpLineTokenizer, lexState: Ref) : Option = let tokenInfoOption, nextLexState = lineTokenizer.ScanToken(lexState.Value) @@ -144,17 +144,14 @@ type internal FSharpColorizationService() = | None -> () , cancellationToken) - // FSROSLYNTODO: Due to issue 12732 on Roslyn side, semantic classification is tied to C#/VB only. - // Once that is exposed to F#, enable the below code path, and add tests accourdingly. - member this.AddSemanticClassificationsAsync(_, _, _, _) = - (* + member this.AddSemanticClassificationsAsync(document: Document, textSpan: TextSpan, result: List, cancellationToken: CancellationToken) = let computation = async { - try - let options = CommonRoslynHelpers.GetFSharpProjectOptionsForRoslynProject(document.Project) + match FSharpLanguageService.GetOptions(document.Project.Id) with + | Some(options) -> let! sourceText = document.GetTextAsync(cancellationToken) |> Async.AwaitTask let! parseResults = FSharpChecker.Instance.ParseFileInProject(document.Name, sourceText.ToString(), options) let! textVersion = document.GetTextVersionAsync(cancellationToken) |> Async.AwaitTask - let! checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, document.Name, textVersion.GetHashCode(), textSpan.ToString(), options) + let! checkResultsAnswer = FSharpChecker.Instance.CheckFileInProject(parseResults, document.FilePath, textVersion.GetHashCode(), textSpan.ToString(), options) let extraColorizationData = match checkResultsAnswer with | FSharpCheckFileAnswer.Aborted -> failwith "Compilation isn't complete yet" @@ -163,13 +160,10 @@ type internal FSharpColorizationService() = |> Seq.toList result.AddRange(extraColorizationData) - with ex -> - Assert.Exception(ex) - raise(ex) + | None -> () } - Task.Run(fun () -> Async.RunSynchronously(computation, cancellationToken = cancellationToken)) - *) - Task.CompletedTask - + + Task.Run(CommonRoslynHelpers.GetTaskAction(computation), cancellationToken) + // Do not perform classification if we don't have project options (#defines matter) member this.AdjustStaleClassification(_: SourceText, classifiedSpan: ClassifiedSpan) : ClassifiedSpan = classifiedSpan diff --git a/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs b/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs index 082fe51949b..2c152f0760c 100644 --- a/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs +++ b/vsintegration/src/FSharp.Editor/DocumentDiagnosticAnalyzer.fs @@ -31,10 +31,11 @@ type internal FSharpDocumentDiagnosticAnalyzer() = 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) - let linePositionSpan = LinePositionSpan(LinePosition(error.StartLineAlternate - 1, error.StartColumn), LinePosition(error.EndLineAlternate - 1, error.EndColumn)) + // F# compiler report errors at start/end of file if parsing fails. It should be corrected to match Roslyn boundaries + let linePositionSpan = LinePositionSpan( + LinePosition(Math.Max(0, error.StartLineAlternate - 1), error.StartColumn), + LinePosition(Math.Max(0, error.EndLineAlternate - 1), error.EndColumn)) let textSpan = sourceText.Lines.GetTextSpan(linePositionSpan) - - // F# compiler report errors at end of file if parsing fails. It should be corrected to match Roslyn boundaries let correctedTextSpan = if textSpan.End < sourceText.Length then textSpan else TextSpan.FromBounds(sourceText.Length - 1, sourceText.Length) Diagnostic.Create(descriptor, Location.Create(filePath, correctedTextSpan , linePositionSpan)) diff --git a/vsintegration/src/FSharp.Editor/DocumentDifferenceService.fs b/vsintegration/src/FSharp.Editor/DocumentDifferenceService.fs deleted file mode 100644 index 7c512c861c5..00000000000 --- a/vsintegration/src/FSharp.Editor/DocumentDifferenceService.fs +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open System -open System.Composition -open System.Collections.Immutable -open System.Threading -open System.Threading.Tasks - -open Microsoft.CodeAnalysis -open Microsoft.CodeAnalysis.Diagnostics -open Microsoft.CodeAnalysis.Host.Mef -open Microsoft.CodeAnalysis.Text -open Microsoft.CodeAnalysis.SolutionCrawler - -open Microsoft.FSharp.Compiler -open Microsoft.FSharp.Compiler.SourceCodeServices -open Microsoft.FSharp.Compiler.Range - -open Microsoft.VisualStudio.FSharp.LanguageService - -[, FSharpCommonConstants.FSharpLanguageName)>] -type FSharpDocumentDifferenceService() = - interface IDocumentDifferenceService with - member this.GetDifferenceAsync(_,_,_) = - // No incremental anaylsis for now. - Task.FromResult(new DocumentDifferenceResult(InvocationReasons.DocumentChanged)) diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index f304c930e6f..40b2bf4cb12 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -32,7 +32,6 @@ - Classification\ColorizationService.fs @@ -49,9 +48,6 @@ Debugging\LanguageDebugInfoService.fs - - Diagnostics\DocumentDifferenceService.fs - Diagnostics\DocumentDiagnosticAnalyzer.fs diff --git a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs index f191051bf24..62bc7bfd47b 100644 --- a/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs +++ b/vsintegration/src/FSharp.Editor/GoToDefinitionService.fs @@ -16,7 +16,7 @@ open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.Classification open Microsoft.CodeAnalysis.Editor open Microsoft.CodeAnalysis.Editor.Host -open Microsoft.CodeAnalysis.Editor.Navigation +open Microsoft.CodeAnalysis.Navigation open Microsoft.CodeAnalysis.Editor.Shared.Utilities open Microsoft.CodeAnalysis.Host.Mef open Microsoft.CodeAnalysis.Text @@ -29,12 +29,15 @@ open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.SourceCodeServices type internal FSharpNavigableItem(document: Document, textSpan: TextSpan, displayString: string) = + member this.DisplayString = displayString + interface INavigableItem with member this.Glyph = Glyph.BasicFile member this.DisplayFileLocation = true - member this.DisplayString = displayString + member this.IsImplicitlyDeclared = false member this.Document = document member this.SourceSpan = textSpan + member this.DisplayTaggedParts = Unchecked.defaultof> member this.ChildItems = ImmutableArray.Empty [] @@ -124,7 +127,7 @@ type internal FSharpGoToDefinitionService [] ([ FSharpNavigableItem // F# API provides only one INavigableItem for presenter in presenters do presenter.DisplayResult(navigableItem.DisplayString, definitionTask.Result) true diff --git a/vsintegration/src/FSharp.Editor/IndentationService.fs b/vsintegration/src/FSharp.Editor/IndentationService.fs index cbe81f700b9..5c6e28546e6 100644 --- a/vsintegration/src/FSharp.Editor/IndentationService.fs +++ b/vsintegration/src/FSharp.Editor/IndentationService.fs @@ -48,11 +48,14 @@ type internal FSharpIndentationService() = interface ISynchronousIndentationService with member this.GetDesiredIndentation(document: Document, lineNumber: int, cancellationToken: CancellationToken): Nullable = - let sourceTextTask= document.GetTextAsync(cancellationToken) + let sourceTextTask = document.GetTextAsync(cancellationToken) sourceTextTask.Wait(cancellationToken) - let sourceText = CommonRoslynHelpers.GetCompletedTaskResult(sourceTextTask) - let tabSize = document.Options.GetOption(FormattingOptions.TabSize, FSharpCommonConstants.FSharpLanguageName) + + let optionsTask = document.GetOptionsAsync(cancellationToken) + optionsTask.Wait(cancellationToken) + let options = CommonRoslynHelpers.GetCompletedTaskResult(optionsTask) + let tabSize = options.GetOption(FormattingOptions.TabSize, FSharpCommonConstants.FSharpLanguageName) match FSharpIndentationService.GetDesiredIndentation(sourceText, lineNumber, tabSize) with | None -> Nullable() diff --git a/vsintegration/src/FSharp.Editor/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService.fs index 412b70d25b1..61499ca7bc1 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService.fs @@ -5,6 +5,8 @@ namespace Microsoft.VisualStudio.FSharp.Editor open System open System.Collections.Generic open System.Runtime.InteropServices +open System.Linq +open System.IO open Microsoft.FSharp.Compiler.SourceCodeServices @@ -15,7 +17,9 @@ open Microsoft.VisualStudio.LanguageServices open Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem open Microsoft.VisualStudio.LanguageServices.Implementation.DebuggerIntelliSense +open Microsoft.VisualStudio.LanguageServices.Implementation.TaskList open Microsoft.VisualStudio.LanguageServices.Implementation +open Microsoft.VisualStudio.LanguageServices.ProjectSystem open Microsoft.VisualStudio.Shell open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.FSharp.LanguageService @@ -27,7 +31,7 @@ type internal SVsSettingsPersistenceManager = class end [] type internal FSharpLanguageService(package : FSharpPackage) = - inherit AbstractLanguageService(package) + inherit AbstractLanguageService(package) static let optionsCache = Dictionary() static member GetOptions(projectId: ProjectId) = @@ -36,6 +40,13 @@ type internal FSharpLanguageService(package : FSharpPackage) = else None + member this.SyncProject(project: AbstractProject, projectContext: IWorkspaceProjectContext, site: IProjectSite) = + let updatedFiles = site.SourceFilesOnDisk() + let workspaceFiles = project.GetCurrentDocuments() |> Seq.map(fun file -> file.FilePath) + + for file in updatedFiles do if not(workspaceFiles.Contains(file)) then projectContext.AddSourceFile(file) + for file in workspaceFiles do if not(updatedFiles.Contains(file)) then projectContext.RemoveSourceFile(file) + override this.ContentTypeName = FSharpCommonConstants.FSharpContentTypeName override this.LanguageName = FSharpCommonConstants.FSharpLanguageName override this.RoslynLanguageName = FSharpCommonConstants.FSharpLanguageName @@ -52,7 +63,6 @@ type internal FSharpLanguageService(package : FSharpPackage) = // FSROSLYNTODO: Hide navigation bars for now. Enable after adding tests workspace.Options <- workspace.Options.WithChangedOption(NavigationBarOptions.ShowNavigationBar, FSharpCommonConstants.FSharpLanguageName, false) - // Ensure that we have a project in the workspace for this document. let (_, buffer) = view.GetBuffer() let filename = VsTextLines.GetFilename buffer let result = VsRunningDocumentTable.FindDocumentWithoutLocking(package.RunningDocumentTable,filename) @@ -61,6 +71,7 @@ type internal FSharpLanguageService(package : FSharpPackage) = match hier with | :? IProvideProjectSite as siteProvider -> let site = siteProvider.GetProjectSite() + let projectGuid = Guid(site.ProjectGuid) let projectFileName = site.ProjectFileName() let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectFileName) @@ -69,14 +80,26 @@ type internal FSharpLanguageService(package : FSharpPackage) = optionsCache.Add(projectId, options) if obj.ReferenceEquals(workspace.ProjectTracker.GetProject(projectId), null) then - let projectSite = new FSharpProjectSite(hier, this.SystemServiceProvider, workspace, projectFileName); - projectSite.Initialize(hier, site) + let projectContextFactory = this.Package.ComponentModel.GetService(); + let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider) + let outputFlag = site.CompilerFlags() |> Seq.pick(fun flag -> + if flag.StartsWith("-o:") then Some(flag.Substring(3)) + else if flag.StartsWith("--out:") then Some(flag.Substring(6)) + else None) + let outputPath = if Path.IsPathRooted(outputFlag) then outputFlag else Path.Combine(Path.GetDirectoryName(projectFileName), outputFlag) + + let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, projectFileName, projectFileName, projectGuid, hier, outputPath, errorReporter) + let project = projectContext :?> AbstractProject + + this.SyncProject(project, projectContext, site) + site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site))) + site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> project.Disconnect())) | _ -> () | _ -> () and [] internal FSharpPackage() = - inherit AbstractPackage() + inherit AbstractPackage() override this.RoslynLanguageName = FSharpCommonConstants.FSharpLanguageName diff --git a/vsintegration/src/FSharp.Editor/ProjectSite.fs b/vsintegration/src/FSharp.Editor/ProjectSite.fs deleted file mode 100644 index 6a7f07bd6e3..00000000000 --- a/vsintegration/src/FSharp.Editor/ProjectSite.fs +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open Microsoft.VisualStudio -open Microsoft.VisualStudio.TextManager.Interop -open Microsoft.VisualStudio.Shell -open Microsoft.VisualStudio.Shell.Interop -open Microsoft.VisualStudio.FSharp.LanguageService -open Microsoft.FSharp.Compiler.SourceCodeServices -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics -open Internal.Utilities.Collections -open System -open System.IO -open System.Diagnostics -open System.Collections.Generic -open Microsoft.CodeAnalysis -open Microsoft.VisualStudio.LanguageServices.Implementation -open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem - -type internal FSharpProjectSite(hierarchy: IVsHierarchy, serviceProvider: System.IServiceProvider, visualStudioWorkspace: VisualStudioWorkspaceImpl, projectName: string) = - inherit AbstractProject(visualStudioWorkspace.ProjectTracker, null, projectName, hierarchy, FSharpCommonConstants.FSharpLanguageName, serviceProvider, visualStudioWorkspace, null) - - member internal this.Initialize(hier: IVsHierarchy, site : IProjectSite) = - this.ProjectTracker.AddProject(this) - - site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName, - new AdviseProjectSiteChanges(fun () -> this.OnProjectSettingsChanged(hier, site))) - - site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName, - new AdviseProjectSiteChanges(fun () -> this.Disconnect())) - - // Add files and references - for file in site.SourceFilesOnDisk() do this.AddDocument(hier, file) - for ref in this.GetReferences(site.CompilerFlags()) do this.AddReference(ref) - - member this.GetReferences(flags : string[]) = - flags |> Array.choose(fun flag -> if flag.StartsWith("-r:") then Some(flag.Substring(3)) else None) - - member this.AddReference(filePath : string) = - this.AddMetadataReferenceAndTryConvertingToProjectReferenceIfPossible(filePath, new MetadataReferenceProperties()) |> ignore - - member this.RemoveReference(filePath: string) = - this.RemoveMetadataReference(filePath) - - member internal this.AddDocument(hier: IVsHierarchy, file : string) = - let itemid = - match hier.ParseCanonicalName(file) with - | (VSConstants.S_OK, id) -> id - | _ -> uint32 VSConstants.VSITEMID.Nil - - let document = this.ProjectTracker.DocumentProvider.TryGetDocumentForFile(this, itemid, file, SourceCodeKind.Regular, fun x -> true) - this.AddDocument(document, true) - - member internal this.OnProjectSettingsChanged(hier: IVsHierarchy, site : IProjectSite) = - let sourceFiles = site.SourceFilesOnDisk() - - // Added files - for file in sourceFiles do if not(this.ContainsFile(file)) then this.AddDocument(hier, file) - // Removed files - let removedDocuments = this.GetCurrentDocuments() |> Seq.where(fun doc -> not(sourceFiles |> Seq.contains(doc.FilePath))) |> Seq.toList - for doc in removedDocuments do this.RemoveDocument(doc) - - let references = this.GetReferences(site.CompilerFlags()) - - // Added references - for ref in references do if not(this.HasMetadataReference(ref)) then this.AddReference(ref) - // Removed references - for ref in this.GetCurrentMetadataReferences() do if not(references |> Seq.contains(ref.FilePath)) then this.RemoveReference(ref.FilePath) diff --git a/vsintegration/src/FSharp.LanguageService/IProjectSite.fs b/vsintegration/src/FSharp.LanguageService/IProjectSite.fs index 4c1b250091a..bc9ecae7302 100644 --- a/vsintegration/src/FSharp.LanguageService/IProjectSite.fs +++ b/vsintegration/src/FSharp.LanguageService/IProjectSite.fs @@ -43,6 +43,9 @@ type internal IProjectSite = /// target framework moniker abstract TargetFrameworkMoniker : string + /// Project Guid + abstract ProjectGuid : string + /// timestamp the site was last loaded abstract LoadTime : System.DateTime diff --git a/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs b/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs index 2a6b34872f3..8c96f1e1928 100644 --- a/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs +++ b/vsintegration/src/FSharp.LanguageService/ProjectSitesAndFiles.fs @@ -35,6 +35,7 @@ type private ProjectSiteOfScriptFile(filename:string, checkOptions : FSharpProje override this.AdviseProjectSiteClosed(_,_) = () override this.IsIncompleteTypeCheckEnvironment = checkOptions.IsIncompleteTypeCheckEnvironment override this.TargetFrameworkMoniker = "" + override this.ProjectGuid = "" override this.LoadTime = checkOptions.LoadTime interface IHaveCheckOptions with @@ -66,6 +67,7 @@ type private ProjectSiteOfSingleFile(sourceFile) = override this.AdviseProjectSiteClosed(_,_) = () override this.IsIncompleteTypeCheckEnvironment = true override this.TargetFrameworkMoniker = "" + override this.ProjectGuid = "" override this.LoadTime = new DateTime(2000,1,1) // any constant time is fine, orphan files do not interact with reloading based on update time /// Information about projects, open files and other active artifacts in visual studio. diff --git a/vsintegration/src/FSharp.ProjectSystem.Base/Project/HierarchyNode.cs b/vsintegration/src/FSharp.ProjectSystem.Base/Project/HierarchyNode.cs index 2ea20da0a74..a97fce3e33b 100644 --- a/vsintegration/src/FSharp.ProjectSystem.Base/Project/HierarchyNode.cs +++ b/vsintegration/src/FSharp.ProjectSystem.Base/Project/HierarchyNode.cs @@ -3031,6 +3031,13 @@ internal string GetTargetFrameworkMoniker() return moniker; } + internal string GetProjectGuid() + { + string guid = projectMgr.GetProjectProperty(ProjectFileConstants.ProjectGuid) as string; + Debug.Assert(!String.IsNullOrEmpty(guid), "No project guid?"); + return guid; + } + internal uint GetTargetFrameworkVersion() { var version = new System.Runtime.Versioning.FrameworkName(GetTargetFrameworkMoniker()).Version; diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index 4daae7e38e0..8b4f43529c3 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -96,6 +96,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem member ips.ErrorListTaskProvider() = inner.ErrorListTaskProvider() member ips.ErrorListTaskReporter() = inner.ErrorListTaskReporter() member ips.TargetFrameworkMoniker = inner.TargetFrameworkMoniker + member ips.ProjectGuid = inner.ProjectGuid member ips.IsIncompleteTypeCheckEnvironment = false member ips.LoadTime = inner.LoadTime @@ -1476,6 +1477,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem closeNotifier.Advise(callbackOwnerKey,callback) member this.IsIncompleteTypeCheckEnvironment = false member this.TargetFrameworkMoniker = x.GetTargetFrameworkMoniker() + member this.ProjectGuid = x.GetProjectGuid() member this.LoadTime = creationTime } @@ -1506,6 +1508,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem member this.AdviseProjectSiteClosed(_,_) = () member this.IsIncompleteTypeCheckEnvironment = false member this.TargetFrameworkMoniker = targetFrameworkMoniker + member this.ProjectGuid = x.GetProjectGuid() member this.LoadTime = creationTime } diff --git a/vsintegration/tests/Salsa/salsa.fs b/vsintegration/tests/Salsa/salsa.fs index a57a55eef2b..90a96c935ab 100644 --- a/vsintegration/tests/Salsa/salsa.fs +++ b/vsintegration/tests/Salsa/salsa.fs @@ -221,7 +221,8 @@ module internal Salsa = try try - GetFlagsAndSources(project,host) + let flagsAndSources = GetFlagsAndSources(project,host) + (project, flagsAndSources) with e -> System.Diagnostics.Debug.Assert(false, sprintf "Bug seen in MSBuild CrackProject: %s %s %s\n" (e.GetType().Name) e.Message (e.StackTrace)) reraise() @@ -257,7 +258,8 @@ module internal Salsa = timestamp <- newtimestamp prevConfig <- curConfig prevPlatform <- curPlatform - flags <- Some(MSBuild.CrackProject(projectfile, prevConfig, prevPlatform)) + let projectObj, projectObjFlags = MSBuild.CrackProject(projectfile, prevConfig, prevPlatform) + flags <- Some(projectObjFlags) match flags with | Some flags -> flags | _ -> raise Error.Bug @@ -291,6 +293,9 @@ module internal Salsa = member this.IsIncompleteTypeCheckEnvironment = false member this.TargetFrameworkMoniker = "" member this.LoadTime = System.DateTime(2000,1,1) + member this.ProjectGuid = + let projectObj, projectObjFlags = MSBuild.CrackProject(projectfile, configurationFunc(), platformFunc()) + projectObj.GetProperty(ProjectFileConstants.ProjectGuid).EvaluatedValue // Attempt to treat as MSBuild project. let internal NewMSBuildProjectSite(configurationFunc, platformFunc, msBuildProjectName) =