Skip to content

Commit

Permalink
Forbid declaring parameters of void type in 'Change Signature'->"Ad…
Browse files Browse the repository at this point in the history
…d parameter" dialog
  • Loading branch information
DoctorKrolic committed Aug 2, 2023
1 parent b3dc95e commit 8cb1abb
Show file tree
Hide file tree
Showing 21 changed files with 143 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.LanguageServices.Implementation.ChangeSignature;
using static Microsoft.VisualStudio.LanguageServices.Implementation.ChangeSignature.ChangeSignatureDialogViewModel;
Expand Down Expand Up @@ -55,5 +56,7 @@ public override SymbolDisplayPart[] GeneratePreviewDisplayParts(AddedParameterVi
public override bool IsTypeNameValid(string typeName) => !SyntaxFactory.ParseTypeName(typeName, options: s_langVersionLatestParseOptions).ContainsDiagnostics;

public override SyntaxNode GetTypeNode(string typeName) => SyntaxFactory.ParseTypeName(typeName);

public override bool IsVoidTypeSyntax(SyntaxNode node) => node is PredefinedTypeSyntax { Keyword.RawKind: (int)SyntaxKind.VoidKeyword };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
AutomationProperties.LabeledBy="{Binding ElementName=TypeNameLabelName}"/>
<StackPanel Orientation="Horizontal" Grid.Row="2" Margin="0,5,0,5">
<imaging:CrispImage Moniker="{x:Static imagecatalog:KnownMonikers.StatusInformation}" Visibility="{Binding TypeIsEmptyImage, Mode=OneWay}"/>
<imaging:CrispImage Moniker="{x:Static imagecatalog:KnownMonikers.StatusError}" Visibility="{Binding TypeDoesNotParseImage, Mode=OneWay}"/>
<imaging:CrispImage Moniker="{x:Static imagecatalog:KnownMonikers.StatusError}" Visibility="{Binding TypeDoesNotParseOrInvalidTypeImage, Mode=OneWay}"/>
<imaging:CrispImage Moniker="{x:Static imagecatalog:KnownMonikers.StatusOK}" Visibility="{Binding TypeBindsImage, Mode=OneWay}"/>
<imaging:CrispImage Moniker="{x:Static imagecatalog:KnownMonikers.StatusWarning}" Visibility="{Binding TypeDoesNotBindImage, Mode=OneWay}"/>
<vs:LiveTextBlock Padding="5 0 0 0" Grid.Row="2" x:Name="TypeBindsTextBlock"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public AddParameterDialogViewModel(Document document, int positionForTypeBinding

TypeIsEmptyImage = Visibility.Visible;
TypeBindsImage = Visibility.Collapsed;
TypeDoesNotParseImage = Visibility.Collapsed;
TypeDoesNotParseOrInvalidTypeImage = Visibility.Collapsed;
TypeDoesNotBindImage = Visibility.Collapsed;
TypeBindsDynamicStatus = ServicesVSResources.Please_enter_a_type_name;

Expand Down Expand Up @@ -104,7 +104,7 @@ public bool IsOptional
public string TypeBindsDynamicStatus { get; set; }
public Visibility TypeBindsImage { get; set; }
public Visibility TypeDoesNotBindImage { get; set; }
public Visibility TypeDoesNotParseImage { get; set; }
public Visibility TypeDoesNotParseOrInvalidTypeImage { get; set; }
public Visibility TypeIsEmptyImage { get; set; }

private string _verbatimTypeName = string.Empty;
Expand All @@ -120,6 +120,8 @@ public string VerbatimTypeName
}
}

private bool _isVoidParameterType;

internal bool CanSubmit([NotNullWhen(false)] out string? message)
{
if (string.IsNullOrEmpty(VerbatimTypeName) || string.IsNullOrEmpty(ParameterName))
Expand All @@ -128,6 +130,12 @@ internal bool CanSubmit([NotNullWhen(false)] out string? message)
return false;
}

if (_isVoidParameterType)
{
message = ServicesVSResources.void_is_not_a_valid_type_for_a_parameter;
return false;
}

if (TypeSymbol == null || !IsParameterTypeSyntacticallyValid(VerbatimTypeName))
{
message = ServicesVSResources.Parameter_type_contains_invalid_characters;
Expand Down Expand Up @@ -175,11 +183,12 @@ private void SendFailureNotification(string message)
private void SetCurrentTypeTextAndUpdateBindingStatus(string typeName)
{
VerbatimTypeName = typeName;
_isVoidParameterType = false;

if (string.IsNullOrWhiteSpace(typeName))
{
TypeIsEmptyImage = Visibility.Visible;
TypeDoesNotParseImage = Visibility.Collapsed;
TypeDoesNotParseOrInvalidTypeImage = Visibility.Collapsed;
TypeDoesNotBindImage = Visibility.Collapsed;
TypeBindsImage = Visibility.Collapsed;
TypeBindsDynamicStatus = ServicesVSResources.Please_enter_a_type_name;
Expand All @@ -191,20 +200,28 @@ private void SetCurrentTypeTextAndUpdateBindingStatus(string typeName)
TypeIsEmptyImage = Visibility.Collapsed;

var languageService = Document.GetRequiredLanguageService<IChangeSignatureViewModelFactoryService>();
TypeSymbol = _semanticModel.GetSpeculativeTypeInfo(PositionForTypeBinding, languageService.GetTypeNode(typeName), SpeculativeBindingOption.BindAsTypeOrNamespace).Type;
var typeNode = languageService.GetTypeNode(typeName);
TypeSymbol = _semanticModel.GetSpeculativeTypeInfo(PositionForTypeBinding, typeNode, SpeculativeBindingOption.BindAsTypeOrNamespace).Type;

var typeParses = IsParameterTypeSyntacticallyValid(typeName);
if (!typeParses || TypeSymbol == null)
if (languageService.IsVoidTypeSyntax(typeNode) || TypeSymbol is { SpecialType: SpecialType.System_Void })
{
_isVoidParameterType = true;
TypeDoesNotParseOrInvalidTypeImage = Visibility.Visible;
TypeDoesNotBindImage = Visibility.Collapsed;
TypeBindsImage = Visibility.Collapsed;
TypeBindsDynamicStatus = ServicesVSResources.void_is_not_a_valid_type_for_a_parameter;
}
else if (!IsParameterTypeSyntacticallyValid(typeName) || TypeSymbol == null)
{
TypeDoesNotParseImage = Visibility.Visible;
TypeDoesNotParseOrInvalidTypeImage = Visibility.Visible;
TypeDoesNotBindImage = Visibility.Collapsed;
TypeBindsImage = Visibility.Collapsed;
TypeBindsDynamicStatus = ServicesVSResources.Type_name_has_a_syntax_error;
}
else
{
var parameterTypeBinds = DoesTypeFullyBind(TypeSymbol);
TypeDoesNotParseImage = Visibility.Collapsed;
TypeDoesNotParseOrInvalidTypeImage = Visibility.Collapsed;

TypeBindsImage = parameterTypeBinds ? Visibility.Visible : Visibility.Collapsed;
TypeDoesNotBindImage = !parameterTypeBinds ? Visibility.Visible : Visibility.Collapsed;
Expand All @@ -217,7 +234,7 @@ private void SetCurrentTypeTextAndUpdateBindingStatus(string typeName)
NotifyPropertyChanged(nameof(TypeBindsDynamicStatus));
NotifyPropertyChanged(nameof(TypeBindsImage));
NotifyPropertyChanged(nameof(TypeDoesNotBindImage));
NotifyPropertyChanged(nameof(TypeDoesNotParseImage));
NotifyPropertyChanged(nameof(TypeDoesNotParseOrInvalidTypeImage));
NotifyPropertyChanged(nameof(TypeIsEmptyImage));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ public abstract SymbolDisplayPart[] GeneratePreviewDisplayParts(
public abstract bool IsTypeNameValid(string typeName);

public abstract SyntaxNode GetTypeNode(string typeName);

public abstract bool IsVoidTypeSyntax(SyntaxNode node);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ internal interface IChangeSignatureViewModelFactoryService : ILanguageService
bool IsTypeNameValid(string typeName);

SyntaxNode GetTypeNode(string typeName);

bool IsVoidTypeSyntax(SyntaxNode node);
}
}
4 changes: 4 additions & 0 deletions src/VisualStudio/Core/Def/ServicesVSResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -2025,4 +2025,8 @@ Additional information: {1}</value>
<data name="Prefer_collection_expression" xml:space="preserve">
<value>Prefer collection expression</value>
</data>
<data name="void_is_not_a_valid_type_for_a_parameter" xml:space="preserve">
<value>'void' is not a valid type for a parameter</value>
<comment>{Locked="void"} "void" represents CLR's 'System.Void' type and should not be localized</comment>
</data>
</root>
5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8cb1abb

Please sign in to comment.