BowlerHatLLC / vscode-as3mxml

ActionScript & MXML language extension for Visual Studio Code. Develop apps for Adobe AIR, Adobe Flash Player, or Apache Royale.
https://as3mxml.com/
Apache License 2.0
256 stars 39 forks source link

The debugger affect to the code #749

Closed ylazy closed 3 months ago

ylazy commented 3 months ago

Hi!

For example I have two classes:

SearchOptions.as

package
{
    public class SearchOptions
    {
        private var _ignoreCase     :Boolean;
        private var _matchWholeWord :Boolean;

        public function SearchOptions():void
        {

        }

        public function get IgnoreCase():SearchOptions
        {
            this.ignoreCase = true;
            return this;
        }

        public function get MatchWholeWord():SearchOptions
        {
            this.matchWholeWord = true;
            return this;
        }

        public function get ignoreCase():Boolean
        {
            return _ignoreCase;
        }

        public function set ignoreCase(value:Boolean):void
        {
            _ignoreCase = value;
        }

        public function get matchWholeWord():Boolean
        {
            return _matchWholeWord;
        }

        public function set matchWholeWord(value:Boolean):void
        {
            _matchWholeWord = value;
        }
    }
}

SearchOption.as

package
{
    public function get SearchOption():SearchOptions
    {
        return new SearchOptions();
    }
}

and I have a code:

var options:SearchOptions = SearchOption.MatchWholeWord;

trace(options.ignoreCase);
trace(options.matchWholeWord);

if (options.ignoreCase)
{
    trace("???");
}

run this code, you will see the expected result:

false
true

But, if you add a breakpoint to the line trace(options.ignoreCase);, then explore the options object in the debugger, then continue, you will see the unexpected result:

true
true
???

Please view the following video capture to see the problem:

https://github.com/BowlerHatLLC/vscode-as3mxml/assets/6010183/b327a6bb-284e-4d29-a732-6fe96f58e51e

This issue happens because the function get IgnoreCase has been executed when I explored the options object in the debugger, it lead to this.ignoreCase = true; executed.

Is there anyway to turn off the auto getting properties when I explore an object?

It's just an example. In fact I ran into many issues similiar to this. For example:

override public function get width():void
{
    if (isInvalidate(INVALIDATE_SIZE)) validateSize();
    return _width;
}

Without any breakpoints, validateSize() will not run. But with a breakpoint, the width property will be get by the debugger if I explore the object, then validateSize() will run.

Please consider to add an option to turn off this feature (property getting) to prevent the debugger to affect to the code.

Thanks!

Adolio commented 3 months ago

Hello!

Except the fact that indeed the debugger can call methods and therefore "interact" with your system, I think your example have design issues. Technically, a getter method should never set things.

The debugger will never call a setter method without you explicitly requesting it. So if you never set things in a getter then you should never have problems with the debugger.

So from my stand point, the get IgnoreCase() & get MatchWholeWord() should actually be constructor parameters.

joshtynjala commented 3 months ago

This issue happens because the function get IgnoreCase has been executed when I explored the options object in the debugger, it lead to this.ignoreCase = true; executed. Is there anyway to turn off the auto getting properties when I explore an object?

This is the intended behavior. There is no way to turn it off.

ylazy commented 3 months ago

@Adolio I know that my examples have design issues. But it's the only way for me, because I want to build something like this:

sub = StringTool.substrBetween(str, StringSearch("foo").IgnoreCase.MatchWholeWord, StringSearch("bar").IgnoreCase, StringSearchOption.StartAt(100).EndAt(400));

It's much more readable than

sub = StringTool.substrBetween(str, "foo", "bar", true, true, true, false, 100, 400);

After a day I solved this by inserting a property check to determine if an object is expanded by the debugger or not.


private var _expandedByDebugger:Boolean;

// when I expand `options` in debugger, this property will be executed first (before any other properties)
// because the debugger will list properties in alphabet order
// so I can know that IgnoreCase and MatchWholeWord are executing by the debugger or not.

private function get ____expandedByDebugger():Boolean
{
    _expandedByDebugger = true;
}

protected function get expandedByDebugger():Boolean
{
    return _expandedByDebugger;
}

public function get IgnoreCase():SearchOptions
{
    if (this.expandedByDebugger) return this; // executing by the debugger => do nothing
    this.ignoreCase = true;
    return this;
}

public function get MatchWholeWord():SearchOptions
{
    if (this.expandedByDebugger) return this; // executing by the debugger => do nothing
    this.matchWholeWord = true;
    return this;
}

Thank you all :)