Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,3 @@ trim_trailing_whitespace = true

[*.{ps1xml,props,xml,yaml}]
indent_size = 2

# CA1303: Do not pass literals as localized parameters
dotnet_diagnostic.CA1303.severity = none
4 changes: 3 additions & 1 deletion src/PowerShellEditorServices.Hosting/BuildInfo.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Globalization;

namespace Microsoft.PowerShell.EditorServices.Hosting
{
public static class BuildInfo
{
public static readonly string BuildVersion = "<development-build>";
public static readonly string BuildOrigin = "<development>";
public static readonly System.DateTime? BuildTime = System.DateTime.Parse("2019-12-06T21:43:41");
public static readonly System.DateTime? BuildTime = System.DateTime.Parse("2019-12-06T21:43:41", CultureInfo.InvariantCulture.DateTimeFormat);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Reflection;
using SMA = System.Management.Automation;
using Microsoft.PowerShell.EditorServices.Hosting;
using System.Globalization;

#if DEBUG
using System.Diagnostics;
Expand Down Expand Up @@ -264,7 +265,7 @@ private void StartLogging()
if (File.Exists(logPath))
{
int randomInt = new Random().Next();
logPath = Path.Combine(logDirPath, $"StartEditorServices-temp{randomInt.ToString("X")}.log");
logPath = Path.Combine(logDirPath, $"StartEditorServices-temp{randomInt.ToString("X", CultureInfo.InvariantCulture.NumberFormat)}.log");
}

var fileLogger = StreamLogger.CreateWithNewFile(logPath);
Expand Down
3 changes: 2 additions & 1 deletion src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ namespace Microsoft.PowerShell.EditorServices.Hosting
/// </summary>
public sealed class EditorServicesLoader : IDisposable
{
private const int Net461Version = 394254;

#if !CoreCLR
private const int Net461Version = 394254;

private static readonly string s_psesBaseDirPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
#endif

Expand Down
11 changes: 11 additions & 0 deletions src/PowerShellEditorServices.Hosting/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "Cmdlet parameters can be arrays", Scope = "module")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "PSES is not localized", Scope = "module")]

[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "PSCmdlet.ThrowTerminatingError() is used instead", Scope = "member", Target = "~M:Microsoft.PowerShell.EditorServices.Commands.StartEditorServicesCommand.EndProcessing")]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could these be placed inline? The ones that target a specific member that is.

Copy link
Contributor Author

@rjmholt rjmholt Jan 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can be. I've never liked those FxCop attributes that occur all over the code (especially when codebases stop using FxCop like in PowerShell), but will leave it up to others

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can certainly see the pros of having the attribute inline, so you get the justification like a comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally agree with @SeeminglyScience about putting them inline so they're "self documenting"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's far from perfect. I hate seeing them too, but it makes it confusing why one thing warns and another doesn't. Most folks aren't going to know to look in that file.

I usually go with #pragma warning disable CA1031 and #pragma warning restore CA1031 since it's slightly less aggressive, but then you lose a lot of information. Probably not suitable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went for the attribute where possible, just since it's got a field for Justification. Some things required a pragma though


[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2208:Instantiate argument exceptions correctly", Justification = "Checking user input from a configuration", Scope = "member", Target = "~M:Microsoft.PowerShell.EditorServices.Hosting.EditorServicesLoader.ValidateConfiguration")]
9 changes: 9 additions & 0 deletions src/PowerShellEditorServices/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "PSES is not localized", Scope = "module")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by created object", Scope = "member", Target = "~M:Microsoft.PowerShell.EditorServices.Hosting.EditorServicesServerFactory.Create(System.String,System.Int32,System.IObservable{System.})~Microsoft.PowerShell.EditorServices.Hosting.EditorServicesServerFactory")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline", Justification = "cctor required for version-specific behavior", Scope = "member", Target = "~M:Microsoft.PowerShell.EditorServices.Services.PowerShellContextService.#cctor")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "PowerShellContext must catch all exceptions for robustness, logging them instead", Scope = "member", Target = "~M:Microsoft.PowerShell.EditorServices.Services.PowerShellContextService.ExecuteCommandAsync``1(System.Management.Automation.PSCommand,System.Text.StringBuilder,Microsoft.PowerShell.EditorServices.Services.PowerShellContext.ExecutionOptions)~System.Threading.Tasks.Task{System.Collections.Generic.IEnumerable{``0}}")]
4 changes: 2 additions & 2 deletions src/PowerShellEditorServices/Server/PsesDebugServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public async Task StartAsync()
.WithHandler<DebugEvaluateHandler>();

logger.LogInformation("Handlers added");
});
}).ConfigureAwait(false);
}

public void Dispose()
Expand All @@ -129,7 +129,7 @@ public void Dispose()

public async Task WaitForShutdown()
{
await _serverStopped.Task;
await _serverStopped.Task.ConfigureAwait(false);
}

#region Events
Expand Down
8 changes: 4 additions & 4 deletions src/PowerShellEditorServices/Server/PsesLanguageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ public async Task StartAsync()
{
await serviceProvider.GetService<PowerShellContextService>().SetWorkingDirectoryAsync(
workspaceService.WorkspacePath,
isPathAlreadyEscaped: false);
isPathAlreadyEscaped: false).ConfigureAwait(false);
}
});
});
}).ConfigureAwait(false);

_serverStart.SetResult(true);
}
Expand All @@ -124,8 +124,8 @@ await serviceProvider.GetService<PowerShellContextService>().SetWorkingDirectory
/// <returns>A task that completes when the server is shut down.</returns>
public async Task WaitForShutdown()
{
await _serverStart.Task;
await LanguageServer.WaitForExit;
await _serverStart.Task.ConfigureAwait(false);
await LanguageServer.WaitForExit.ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShellContext
internal class ConsoleReadLine
{
#region Private Field
private PowerShellContextService powerShellContext;
private readonly PowerShellContextService powerShellContext;

#endregion

Expand Down Expand Up @@ -48,8 +48,9 @@ public async Task<SecureString> ReadSecureLineAsync(CancellationToken cancellati
{
SecureString secureString = new SecureString();

int initialPromptRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken);
int initialPromptCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken);
// TODO: Are these values used?
int initialPromptRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false);
int initialPromptCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int previousInputLength = 0;

Console.TreatControlCAsInput = true;
Expand All @@ -58,7 +59,7 @@ public async Task<SecureString> ReadSecureLineAsync(CancellationToken cancellati
{
while (!cancellationToken.IsCancellationRequested)
{
ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken);
ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken).ConfigureAwait(false);

if ((int)keyInfo.Key == 3 ||
keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control))
Expand Down Expand Up @@ -96,8 +97,8 @@ public async Task<SecureString> ReadSecureLineAsync(CancellationToken cancellati
}
else if (previousInputLength > 0 && currentInputLength < previousInputLength)
{
int row = await ConsoleProxy.GetCursorTopAsync(cancellationToken);
int col = await ConsoleProxy.GetCursorLeftAsync(cancellationToken);
int row = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false);
int col = await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false);

// Back up the cursor before clearing the character
col--;
Expand Down Expand Up @@ -127,14 +128,14 @@ public async Task<SecureString> ReadSecureLineAsync(CancellationToken cancellati

#region Private Methods

private static async Task<ConsoleKeyInfo> ReadKeyAsync(CancellationToken cancellationToken)
private static Task<ConsoleKeyInfo> ReadKeyAsync(CancellationToken cancellationToken)
{
return await ConsoleProxy.ReadKeyAsync(intercept: true, cancellationToken);
return ConsoleProxy.ReadKeyAsync(intercept: true, cancellationToken);
}

private async Task<string> ReadLineAsync(bool isCommandLine, CancellationToken cancellationToken)
private Task<string> ReadLineAsync(bool isCommandLine, CancellationToken cancellationToken)
{
return await this.powerShellContext.InvokeReadLineAsync(isCommandLine, cancellationToken);
return this.powerShellContext.InvokeReadLineAsync(isCommandLine, cancellationToken);
}

/// <summary>
Expand All @@ -154,6 +155,7 @@ private async Task<string> ReadLineAsync(bool isCommandLine, CancellationToken c
/// </returns>
internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, CancellationToken cancellationToken)
{
// TODO: Is inputBeforeCompletion used?
string inputBeforeCompletion = null;
string inputAfterCompletion = null;
CommandCompletion currentCompletion = null;
Expand All @@ -163,9 +165,10 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel

StringBuilder inputLine = new StringBuilder();

int initialCursorCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken);
int initialCursorRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken);
int initialCursorCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false);
int initialCursorRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false);

// TODO: Are these used?
int initialWindowLeft = Console.WindowLeft;
int initialWindowTop = Console.WindowTop;

Expand All @@ -177,7 +180,7 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
{
while (!cancellationToken.IsCancellationRequested)
{
ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken);
ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken).ConfigureAwait(false);

// Do final position calculation after the key has been pressed
// because the window could have been resized before then
Expand Down Expand Up @@ -207,14 +210,15 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
command.AddParameter("CursorColumn", currentCursorIndex);
command.AddParameter("Options", null);

var results =
await this.powerShellContext.ExecuteCommandAsync<CommandCompletion>(command, false, false);
var results = await this.powerShellContext
.ExecuteCommandAsync<CommandCompletion>(command, sendOutputToHost: false, sendErrorToHost: false)
.ConfigureAwait(false);

currentCompletion = results.FirstOrDefault();
}
else
{
using (RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandleAsync())
using (RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandleAsync().ConfigureAwait(false))
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.Runspace = runspaceHandle.Runspace;
Expand Down Expand Up @@ -325,11 +329,9 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
PSCommand command = new PSCommand();
command.AddCommand("Get-History");

currentHistory =
await this.powerShellContext.ExecuteCommandAsync<PSObject>(
command,
false,
false) as Collection<PSObject>;
currentHistory = await this.powerShellContext.ExecuteCommandAsync<PSObject>(command, sendOutputToHost: false, sendErrorToHost: false)
.ConfigureAwait(false)
as Collection<PSObject>;

if (currentHistory != null)
{
Expand Down Expand Up @@ -475,7 +477,7 @@ await this.powerShellContext.ExecuteCommandAsync<PSObject>(
inputLine,
promptStartCol,
promptStartRow,
keyInfo.KeyChar.ToString(),
keyInfo.KeyChar.ToString(), // TODO: Determine whether this should take culture into account
currentCursorIndex,
finalCursorIndex: currentCursorIndex + 1);
}
Expand All @@ -489,6 +491,7 @@ await this.powerShellContext.ExecuteCommandAsync<PSObject>(
return null;
}

// TODO: Is this used?
private int CalculateIndexFromCursor(
int promptStartCol,
int promptStartRow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class ExtensionService
{
#region Fields

private Dictionary<string, EditorCommand> editorCommands =
private readonly Dictionary<string, EditorCommand> editorCommands =
new Dictionary<string, EditorCommand>();

private readonly ILanguageServer _languageServer;
Expand Down Expand Up @@ -88,7 +88,7 @@ public async Task InitializeAsync(

// Register the editor object in the runspace
PSCommand variableCommand = new PSCommand();
using (RunspaceHandle handle = await this.PowerShellContext.GetRunspaceHandleAsync())
using (RunspaceHandle handle = await this.PowerShellContext.GetRunspaceHandleAsync().ConfigureAwait(false))
{
handle.Runspace.SessionStateProxy.PSVariable.Set(
"psEditor",
Expand All @@ -104,9 +104,8 @@ public async Task InitializeAsync(
/// <returns>A Task that can be awaited for completion.</returns>
public async Task InvokeCommandAsync(string commandName, EditorContext editorContext)
{
EditorCommand editorCommand;

if (this.editorCommands.TryGetValue(commandName, out editorCommand))
if (this.editorCommands.TryGetValue(commandName, out EditorCommand editorCommand))
{
PSCommand executeCommand = new PSCommand();
executeCommand.AddCommand("Invoke-Command");
Expand All @@ -115,8 +114,8 @@ public async Task InvokeCommandAsync(string commandName, EditorContext editorCon

await this.PowerShellContext.ExecuteCommandAsync<object>(
executeCommand,
!editorCommand.SuppressOutput,
true);
sendOutputToHost: !editorCommand.SuppressOutput,
sendErrorToHost: true).ConfigureAwait(false);
}
else
{
Expand All @@ -135,6 +134,11 @@ await this.PowerShellContext.ExecuteCommandAsync<object>(
/// <returns>True if the command is newly registered, false if the command already exists.</returns>
public bool RegisterCommand(EditorCommand editorCommand)
{
if (editorCommand is null)
{
throw new ArgumentNullException(nameof(editorCommand));
}

bool commandExists =
this.editorCommands.ContainsKey(
editorCommand.Name);
Expand All @@ -160,8 +164,7 @@ public bool RegisterCommand(EditorCommand editorCommand)
/// <param name="commandName">The name of the command to be unregistered.</param>
public void UnregisterCommand(string commandName)
{
EditorCommand existingCommand = null;
if (this.editorCommands.TryGetValue(commandName, out existingCommand))
if (this.editorCommands.TryGetValue(commandName, out EditorCommand existingCommand))
{
this.editorCommands.Remove(commandName);
this.OnCommandRemoved(existingCommand);
Expand Down
Loading