Skip to content

Commit ab291da

Browse files
committed
Ensure new files are formatted based on the right language version
1 parent dc2548f commit ab291da

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

src/VisualStudio/CSharp/Impl/LanguageService/CSharpEditorFactory.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#nullable disable
66

77
using System;
8+
using System.Diagnostics;
89
using System.Diagnostics.CodeAnalysis;
910
using System.Runtime.InteropServices;
1011
using System.Threading;
1112
using System.Threading.Tasks;
1213
using Microsoft.CodeAnalysis;
14+
using Microsoft.CodeAnalysis.CSharp;
1315
using Microsoft.CodeAnalysis.CSharp.CodeGeneration;
1416
using Microsoft.CodeAnalysis.CSharp.FileHeaders;
1517
using Microsoft.CodeAnalysis.CSharp.MisplacedUsingDirectives;
@@ -18,6 +20,8 @@
1820
using Microsoft.CodeAnalysis.FileHeaders;
1921
using Microsoft.VisualStudio.ComponentModelHost;
2022
using Microsoft.VisualStudio.LanguageServices.Implementation;
23+
using Microsoft.VisualStudio.LanguageServices.Utilities;
24+
using Microsoft.VisualStudio.Shell.Interop;
2125

2226
namespace Microsoft.VisualStudio.LanguageServices.CSharp.LanguageService
2327
{
@@ -32,5 +36,22 @@ public CSharpEditorFactory(IComponentModel componentModel)
3236

3337
protected override string ContentTypeName => ContentTypeNames.CSharpContentType;
3438
protected override string LanguageName => LanguageNames.CSharp;
39+
40+
protected override Solution GetSolutionWithCorrectParseOptionsForProject(ProjectId projectId, IVsHierarchy hierarchy, Solution solution)
41+
{
42+
var project = solution.GetProject(projectId);
43+
44+
Debug.Assert(project is not null);
45+
46+
if (project.ParseOptions is CSharpParseOptions parseOptions &&
47+
hierarchy is IVsBuildPropertyStorage propertyStorage &&
48+
ErrorHandler.Succeeded(propertyStorage.GetPropertyValue("LangVersion", null, (uint)_PersistStorageType.PST_PROJECT_FILE, out var langVersionString)) &&
49+
LanguageVersionFacts.TryParse(langVersionString, out var langVersion))
50+
{
51+
return solution.WithProjectParseOptions(projectId, parseOptions.WithLanguageVersion(langVersion));
52+
}
53+
54+
return solution;
55+
}
3556
}
3657
}

src/VisualStudio/Core/Def/Implementation/AbstractEditorFactory.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ protected AbstractEditorFactory(IComponentModel componentModel)
4646
protected abstract string ContentTypeName { get; }
4747
protected abstract string LanguageName { get; }
4848

49+
protected abstract Solution GetSolutionWithCorrectParseOptionsForProject(ProjectId projectId, IVsHierarchy hierarchy, Solution solution);
50+
4951
public void SetEncoding(bool value)
5052
=> _encoding = value;
5153

@@ -325,6 +327,12 @@ private async Task FormatDocumentCreatedFromTemplateAsync(IVsHierarchy hierarchy
325327
projectIdToAddTo = temporaryProject.Id;
326328
}
327329

330+
// We need to ensure that decisions made during new document formatting are based on the right language
331+
// version from the project system, but the NotifyItemAdded event happens before a design time build,
332+
// and someimes before we have even been told about the projects existence, so we have to ask the hierarchy
333+
// for the language version to use.
334+
solution = GetSolutionWithCorrectParseOptionsForProject(projectIdToAddTo, hierarchy, solution);
335+
328336
var documentId = DocumentId.CreateNewId(projectIdToAddTo);
329337
var forkedSolution = solution.AddDocument(DocumentInfo.Create(documentId, filePath, loader: new FileTextLoader(filePath, defaultEncoding: null), filePath: filePath));
330338
var addedDocument = forkedSolution.GetDocument(documentId)!;

src/VisualStudio/VisualBasic/Impl/LanguageService/VisualBasicEditorFactory.vb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ Imports Microsoft.CodeAnalysis
77
Imports Microsoft.CodeAnalysis.Editing
88
Imports Microsoft.CodeAnalysis.Editor
99
Imports Microsoft.CodeAnalysis.FileHeaders
10+
Imports Microsoft.CodeAnalysis.VisualBasic
1011
Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
1112
Imports Microsoft.CodeAnalysis.VisualBasic.FileHeaders
1213
Imports Microsoft.VisualStudio.ComponentModelHost
1314
Imports Microsoft.VisualStudio.LanguageServices.Implementation
15+
Imports Microsoft.VisualStudio.Shell.Interop
1416

1517
Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
1618
<Guid(Guids.VisualBasicEditorFactoryIdString)>
@@ -24,5 +26,33 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
2426
Protected Overrides ReadOnly Property ContentTypeName As String = ContentTypeNames.VisualBasicContentType
2527

2628
Protected Overrides ReadOnly Property LanguageName As String = LanguageNames.VisualBasic
29+
30+
Protected Overrides Function GetSolutionWithCorrectParseOptionsForProject(projectId As ProjectId, hierarchy As IVsHierarchy, solution As Solution) As Solution
31+
Dim project = solution.GetProject(projectId)
32+
33+
Debug.Assert(project IsNot Nothing)
34+
35+
Dim parseOptions = TryCast(project.ParseOptions, VisualBasicParseOptions)
36+
If parseOptions Is Nothing Then
37+
Return solution
38+
End If
39+
40+
Dim propertyStorage = TryCast(hierarchy, IVsBuildPropertyStorage)
41+
If propertyStorage Is Nothing Then
42+
Return solution
43+
End If
44+
45+
Dim langVersionString = ""
46+
If ErrorHandler.Failed(propertyStorage.GetPropertyValue("LangVersion", Nothing, CUInt(_PersistStorageType.PST_PROJECT_FILE), langVersionString)) Then
47+
Return solution
48+
End If
49+
50+
Dim langVersion = LanguageVersion.Default
51+
If TryParse(langVersionString, langVersion) Then
52+
Return solution.WithProjectParseOptions(projectId, parseOptions.WithLanguageVersion(langVersion))
53+
End If
54+
55+
Return solution
56+
End Function
2757
End Class
2858
End Namespace

0 commit comments

Comments
 (0)