GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Aggregate exceptions when parsing a settings hashtable by travisclagrone · Pull Request #1275 · PowerShell/PSScriptAnalyzer

Conversation

@travisclagrone

@travisclagrone Travis C. LaGrone (travisclagrone) commented Jun 25, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This pull request aggregates exceptions raised about any hashtable argument to the -Settings parameter of the Invoke-ScriptAnalyzer command in order to output information about all knowable such exceptions in the same invocation (as opposed to outputting only one per invocation). Concomitantly, this pull request refines the related exception message resource strings in order to increase the specificity and granularity thereof.

The expected benefits include improving both the usefulness as well as the usability of exceptions raised about any hashtable argument to the -Settings parameter of the Invoke-ScriptAnalyzer command. Usefulness is improved via more informative (specific and granular) exception messages. Usability is improved via aggregating all knowable such exceptions, which renders any multi-exceptional -Settings hashtable argument debuggable after a single attempted execution (e.g. as part of automated testing), as opposed to requiring multiple debugging cycles to surface each such problem despite independence thereof.

Example

Given

$settings = @{
    foo = 'bar'
    CustomRulePath = $null
    IncludeRules = @(
        $null
        42
    )
}

When

Invoke-ScriptAnalyzer -ScriptDefinition 'Write-Output "Hello, world!"' -Settings $settings

Old behavior

Only one problem is ambiguously reported.

Invoke-ScriptAnalyzer : Value  for key CustomRulePath has the wrong data type.
At line:1 char:1
+ Invoke-ScriptAnalyzer -ScriptDefinition 'Write-Output "Hello, world!" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidData: (System.Collections.Hashtable:Hashtable) [Invoke-ScriptAnalyzer], InvalidDataException
+ FullyQualifiedErrorId : SETTINGS_ERROR,Microsoft.Windows.PowerShell.ScriptAnalyzer.Commands.InvokeScriptAnalyzerCommand

New behavior

All detectable problems are reported.

Invoke-ScriptAnalyzer : One or more errors occurred. (The setting 'CustomRulePath' value is null.) (The setting 'IncludeRules', index 0 element is null.) (The setting 'IncludeRules', index 1 element, value '42' is not a string type.) (foo is not a valid key in the settings hashtable. Valid keys are CustomRulePath, ExcludeRules, IncludeRules, IncludeDefaultRules, RecurseCustomRulePath, Rules and Severity.)
At line:1 char:1
+ Invoke-ScriptAnalyzer -ScriptDefinition 'Write-Output "Hello, world!" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidData: (System.Collections.Hashtable:Hashtable) [Invoke-ScriptAnalyzer], AggregateException
+ FullyQualifiedErrorId : SETTINGS_ERROR,Microsoft.Windows.PowerShell.ScriptAnalyzer.Commands.InvokeScriptAnalyzerCommand

Future Work

  • Flesh out formal specifications and test cases pertaining to exceptional behavior when parsing a hashtable argument to the -Settings parameter of the Invoke-ScriptAnalyzer command.
  • Generalize the concept of this pull request into a PSScriptAnalyzer rule.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Travis C. LaGrone (travisclagrone) added 30 commits June 22, 2019 19:34
@travisclagrone
Annotatively research current state of exception handling surrounding…
f8f8083
… settings file load invocation
@travisclagrone
Throw a contextful terminating error if processing the argument of 'I…
b75dced
…nvoke-ScriptAnalyzer -Settings' results in an exception
@travisclagrone
Refine id and category of error for when processing value of `Invoke-…
6648344
…ScriptAnalyzer -Settings` results in an exception
@travisclagrone
Revert "Annotatively research current state of exception handling sur…
0472359
…rounding settings file load invocation"

This reverts commit 3bfd45b.
@travisclagrone
Do not attempt id and category inference for the error to throw when …
a012dec
…processing the argument of `Invoke-ScriptAnalyzer -Settings` results in an exception
@travisclagrone
Remove using System.IO
88ab1ec
@travisclagrone
Revert "Remove using System.IO"
2faab31
This reverts commit 88ab1ec.

`using System.IO` is required in Engine\Settings.cs after all. The main
use is for pre-existing unqualified references to the type
InvalidDataException.
@travisclagrone
Remove unused local variable, 'validKeys'
05f6795
@travisclagrone
Remove GetDictionaryFromHashtable(Hashtable)
cc3323b
@travisclagrone
Validate that no key is null
70035d6
@travisclagrone
Validate that every key is a string
e3037f7
@travisclagrone
Validate that no value is null
b6ac61b
@travisclagrone
Validate that every key is unique, ignoring case
4cf6aca
@travisclagrone
Extract validation of "Rules" setting dictionary type from method Str…
3a5380b
…ings.ConvertToRuleArgumentType(Dictionary<string, object>)
@travisclagrone
Extract validation of dictionary key case-insensitivity from method S…
4ace3b9
…ettings.ConvertToRuleArgumentType(Dictionary<string, objct>)
@travisclagrone
Extract validation of "Rules" setting values dictionary types from me…
cfd7037
…thod Strings.ConvertToRuleArgumentType(Dictionary<string, object>)
@travisclagrone
Remove method Settings.ConvertToRuleArgumentType(Dictionary<string, o…
0736242
…bject>)
@travisclagrone
Merge branch 'refactor-out-ConvertToRuleArgumentType' into refactor-o…
c1e9da5
…ut-GetDictionaryFromHashTable
@travisclagrone
Refactor validation of setting "Rules" type to accommodate finer-fide…
ef510c9
…lity validation
@travisclagrone
Validate that each key of the "Rules" setting is nonnull
cd031f8
@travisclagrone
Validate that each key of the "Rules" setting is a string
0193e28
@travisclagrone
Validate that each key of the "Rules" setting is unique, ignoring case
74df2e1
@travisclagrone
Validate that each value of the "Rules" setting is nonnull
5baba1e
@travisclagrone
Refactor validation that each value of the "Rules" setting is a dicti…
b495b24
…onary type
@travisclagrone
Validate that each setting rule argument key is nonnull
f55735f
@travisclagrone
Validate that each setting rule argument key is of type string
062bbd3
@travisclagrone
Validate that each setting rule argument key is unique, ignore case
051f345
@travisclagrone
Validate that each setting rule argument value is nonnull
ac1b17a
@travisclagrone
Assign parse of settings "Rules" to Settings.ruleArguments
1cfaa67
@travisclagrone
Merge branch 'refactor-out-GetDictionaryFromHashTable' into aggregate…
072e2f5
…-settings-file-exceptions
Travis C. LaGrone (travisclagrone) added 4 commits June 24, 2019 19:48
@travisclagrone
Aggregate exceptions within ParseSetingsHashtable(Hashtable)
ea0d1b6
@travisclagrone
Aggregate exceptions in ParseSettingValueBoolean(object, string) by a…
f43dc67
…dding IList<Exception> parameter
@travisclagrone
Aggregate exceptions in ParseSettingValueStringOrStrings(object, stri…
09222c6
…ng) by adding IList<Exception> parameter
@travisclagrone
Merge branch 'implement-AggregateException-for-ParseSettingsHashtable…
a1b7a8f
…_Hashtable' into aggregate-settings-file-exceptions
@travisclagrone Travis C. LaGrone (travisclagrone) changed the title Merge branch 'implement-AggregateException-for-ParseSettingsHashtable_Hashtable' into aggregate-settings-file-exceptions Aggregate exceptions when parsing a settings hashtable Jun 25, 2019
@travisclagrone

Travis C. LaGrone (travisclagrone) commented Jun 29, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Christoph Bergmeister (@bergmeister) Would you be opposed to me redoing your most recent commit ba31f6b, "Merge branch 'master' of PowerShell/PSScriptAnalyzer into aggregate-settings-file-exceptions", as a rebase in order to simplify the preceding commit list for this pull request?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bergmeister

Christoph Bergmeister (bergmeister) commented Jun 29, 2019

Copy link
Copy Markdown
Collaborator

My last commit only pulled the latest changes from master into it to resolve the merge conflict due to the merge of PR #1263 It's up to you if you want to rebase your branch or revert my last commit

About the PR itself: Can you please describe the benefit of it from a user's perspective by giving e.g. an example.
Apart from aggregating the exceptions, a lot of the logic was refactored as well, was there a reason for it? Since the original maintainer who wrote the tool, has left and we do not have much test coverage in some areas, making that many changes makes me a bit nervous. If you could please self-review and leave some comments in the PR on the reason for the change in some areas, it would help us to review and understand the proposed changes in this PR. If this PR really makes the errors more useful or fixes bugs in the existing code, then we definitely want to consider the PR :-)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@travisclagrone
Travis C. LaGrone (travisclagrone) force-pushed the aggregate-settings-file-exceptions branch 2 times, most recently from ef013b1 to a1b7a8f Compare June 30, 2019 08:29
Travis C. LaGrone (travisclagrone) added 2 commits June 30, 2019 03:36
@travisclagrone
Merge branch 'master' into aggregate-settings-file-exceptions
ff27165
@travisclagrone
Debug exceptional element index incrementing in method Settings.Parse…
cae559c
…SettingValueStringOrStrings(object, string, IList<Exception>)
@travisclagrone

Travis C. LaGrone (travisclagrone) commented Jun 30, 2019

Copy link
Copy Markdown
Contributor Author

Christoph Bergmeister (@bergmeister) I have updated the description of this pull request with a synopsis of the changes and expected benefits, as well as an illustrative example. If a more detailed code review is required, could you please provide an example for me and/or some pointers as to which region(s) need reviewing? (Without going into commentary about my previous jobs, suffice to say this will be my first "real" code review of this sort.) Many thanks in advance!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bergmeister
Christoph Bergmeister (bergmeister) approved these changes Jun 30, 2019
View reviewed changes

@bergmeister Christoph Bergmeister (bergmeister) left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Thanks for the efforts. It looks good to me, only 2 minor comments with one being optional. I added 2 more reviewers so that at least 1 more pair of eyes double checks it as well, I did some manual smoke testing and it looks good to me.
Out of curiosity: Do you use VS-Code or Visual Studio for development? Visual Studio can auto-generate the *.Designer.cs files but not VS-Code. As far as I was aware, the old helper script New-StronglyTypedCsFileForResx.ps1 is broken but to me it looks like you've used it and it works somehow (maybe it suddenly started to work in a newer version of the .Net Core SDK...). On a related note: In the next upcoming preview 7 of the .Net Core 3 SDK, dotnet build will be able to auto-generate the resources for us.

About your 2 future items: Yes, we'd definitely welcome more test cases. Please open an issue about the PSSA rule that you plan to write for validation.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bergmeister Christoph Bergmeister (bergmeister) added the Area - Engine label Jun 30, 2019
@bergmeister
Christoph Bergmeister (bergmeister) requested review from James Truher (JamesWTruher) and Rob Holt (rjmholt) June 30, 2019 12:45
@travisclagrone

Travis C. LaGrone (travisclagrone) commented Jun 30, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Ok, thank you. I will wait for any additional review before further action on my part.

Yes, I have been using VS Code with the New-StronglyTypedCsFileForResx.ps1 script. Should I stop using and/or deprecate that script?

I will see about opening an issue this coming week for each of the two "future work" items.

bergmeister reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bergmeister

Christoph Bergmeister (bergmeister) commented Jun 30, 2019

Copy link
Copy Markdown
Collaborator

If the script worked fine for you, then there shouldn't be a problem with it, apart from occasional merge conflicts, it was only a surprise to me that the script works as I was under the impression it didn't a year ago, maybe it is just an update in the .Net SDK but once .Net Core 3 is RTM, we can use it and the build process will do that work for us automatically and then we can probably remove the files from source control...

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

JamesWTruher
James Truher (JamesWTruher) reviewed Jul 2, 2019
View reviewed changes

@JamesWTruher James Truher (JamesWTruher) left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

nothing blocking here

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Engine/Settings.cs
return (bool) value;
}

private void ParseSettingsHashtable(Hashtable settings)

@JamesWTruher James Truher (JamesWTruher) Jul 2, 2019

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I think this may have more global utility. Could this be public?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@travisclagrone Travis C. LaGrone (travisclagrone) Jul 5, 2019

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Should this really be made public without also making it static? If so, then I will go ahead and make the change. If not, then if this should be changed to be both public and static, then I would ask to postpone this change to a subsequent pull request in which additional related refactorings can be made. This is because--as far as I understand it--rendering a Settings object constructible via a static Parse...(Hashtable) method (i.e. a factory method) should be coupled with deprecating its constructibility from a yet-to-be-parsed Hashtable via a public constructor, and thus also refactoring any extant client logic (e.g. in the "Engine/Settings/InvokeScriptAnalyzerCommands.cs" file).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings.cs
string ruleName = rule.Key as string;

if (!uniqueRuleKeys.Add(ruleName))
{

@JamesWTruher James Truher (JamesWTruher) Jul 2, 2019

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

it looks like the first element to cause an error will move on to the next element, so if there are multiple issues, they won't be caught until the user fixes the previous break. Is there a way to keep going on in some of these cases and find all the issues in the setting?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@travisclagrone Travis C. LaGrone (travisclagrone) Jul 5, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

James Truher (@JamesWTruher) Which case(s) in particular are you referring to? To the best of my knowledge, I have sequenced the checks here such that there is no case where a preceding failed check (that currently results in a continue) would either semantically or logically allow a subsequent check (on the same element) to be performed. The only exception I can see is perhaps the uniqueness constraint, which I will update momentarily to not continue on failure.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@travisclagrone Travis C. LaGrone (travisclagrone) Jul 5, 2019

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

c7ff89b updates the uniqueness check to not continue to the next element on failure, but rather proceed to check the current element's value as well.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Engine/Settings.cs Resolved

Uh oh!

There was an error while loading. Please reload this page.

Travis C. LaGrone (travisclagrone) added 6 commits July 4, 2019 18:55
@travisclagrone
Trim trailing whitespace
cf2504b
@travisclagrone
Do not continue if a "Rules" setting key is non-unique
c7ff89b
@travisclagrone
Refactor Settings constructor to use the guard chain pattern
d54384f
@travisclagrone
Refactor ParseSettingsFile(string) => void to `static ParseSettings…
25710df
…FileToHashtable(string) => Hashtable`
@travisclagrone
Fix sequencing of invocation of ParseSettingsFileToHashtable in `Se…
215f0e2
…ttings` constructor

Fixes previous commit 25710df
@travisclagrone
Merge branch 'simplify-settings-constructor' into aggregate-settings-…
417347a
…file-exceptions
@bergmeister

Christoph Bergmeister (bergmeister) commented Jul 6, 2019

Copy link
Copy Markdown
Collaborator

James Truher (@JamesWTruher) Are you happy now with the changes that were made?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

rjmholt
Rob Holt (rjmholt) reviewed Jul 8, 2019
View reviewed changes

@rjmholt Rob Holt (rjmholt) left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I think there's some interesting stuff in here, but to carry out the error collect/recover parse pattern I think the right way to do it is actually:

  • Create a new class (non singleton) specifically for parsing a settings file
  • Give it private recursive descent style methods for parsing the file and a private field for a list of exceptions
  • Give it public entry points for each variant of settings you expect, like:
    • public PssaSettings ReadSettingsFromFile(string settingsPath, out List<Exception> errors)
    • public PssaSettings ReadSettingsFromHashtable(Hashtable settingsValue, out List<Exception> errors)
  • Use pattern matching and recursive descent to read the settings and add to the errors on the fly

One example of a recursive descent reader like this is here and an example of error-aggregating validation is here.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Commands/InvokeScriptAnalyzerCommand.cs
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;

@rjmholt Rob Holt (rjmholt) Jul 2, 2019

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Given that this is the only change in this file, I'm assuming this isn't used and can be taken out?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings.cs
}

private List<string> GetData(object val, string key)
private List<string> ParseSettingValueStringOrStrings(object value, string settingName, IList<Exception> exceptions)

@rjmholt Rob Holt (rjmholt) Jul 3, 2019

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I think a method with StringOrStrings in it is a strong indicator that this method should be broken into an overload for string and overload for IReadOnlyList<string> and an entry point overload for object that uses a pattern match switch.

Also Parse doesn't really indicate well what's going on, since we're not trying to read this from a string. I think this a Convert or similar.

So I'd imagine this being written like this:

private List<string> GetSettingFromInput(object value, string settingName, ref List<Exception> exceptions)
{
    switch (value)
    {
        case null:
            exceptions.Add(...);
            return null;

        case string str:
            return GetSettingFromInput(str, settingName, ref exceptions);

        case IEnumerable enumerable:
            return GetSettingFromInput(enumerable, settingName, ref exceptions);

        default:
            exceptions.Add(...);
            return null;
    }
}

private List<string> GetSettingFromInput(string str, string settingName, ref List<Exception> exception)
{
        return GetSettingFromInput(new [] { str }, settingName, ref exception);
}

private List<string> GetSettingFromInput(IEnumerable enumerable, string settingName, ref List<Exception> exceptions)
{
    var settings = new List<string>();
    foreach (object element in enumerable)
    {
        if (element == null)
        {
            exceptions.Add(...);
            continue;
        }

        if (!(element is string strElement))
        {
            exceptions.Add(...);
            continue;
        }

        settings.Add(strElement);
    }
    return settings;
}

Note that here you don't need to use ref to pass the List<Exception>, but it helps to indicate that you intend it to be both passed in and mutated. The other possibility would be to return a tuple to lower the onus on the caller.

I don't see you use the settingName variable anywhere other than errors, but presumably that's just a question of error tracing.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings.cs
severities = new List<string>();
ruleArguments = new Dictionary<string, Dictionary<string, object>>(StringComparer.OrdinalIgnoreCase);
var settingsFilePath = settings as string;
this.includeRules = new List<string>();

@rjmholt Rob Holt (rjmholt) Jul 8, 2019

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

If a change like this is made, I think it may as well be a change to _includeRules instead. That's admittedly more of a style opinion, but it's consistent with other PowerShell code and a less verbose way of designating a private field.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings.cs
}

if (hashtable == null)
if (hashtable is null)

@rjmholt Rob Holt (rjmholt) Jul 8, 2019 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

== is more appropriate here since it really does test referential equality. The only language I know where is is conventional for a nullity check is Python (because it doesn't really have a null, but a singleton object None that references default to).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bergmeister

Christoph Bergmeister (bergmeister) commented Jan 4, 2020

Copy link
Copy Markdown
Collaborator

travis-c-lagrone Are you still interested in continuing the PR?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rjmholt

Rob Holt (rjmholt) commented Apr 21, 2021

Copy link
Copy Markdown
Contributor

Closing this PR as abandoned

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@rjmholt Rob Holt (rjmholt) closed this Apr 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@bergmeister Christoph Bergmeister (bergmeister) bergmeister approved these changes
+2 more reviewers
@rjmholt Rob Holt (rjmholt) rjmholt left review comments
@JamesWTruher James Truher (JamesWTruher) JamesWTruher left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

Area - Engine

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@travisclagrone @bergmeister @rjmholt @JamesWTruher
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.