@PeterMTaylor This only relates to usages of controls on MSForms.UserForm designers. Host implementations/wrappers may and do differ. MSForms.Textbox on a UserForm <> Textbox on a worksheet <> Textbox on a PowerPoint slide <> Textbox on an Access Form/Report.
> Note If these functions are passed NULL pointers, there will be an access violation and the program will crash. It is your responsibility to protect these functions against NULL pointers.
Just took a look at a crash dump - it seems that vbe7 is trying to free the memory that I'm allocating with Marshal.AllocHGlobal and falling on its face.
> For VT_BSTR, there is only one owner for the string. All strings in variants must be allocated with the SysAllocString function. When releasing or changing the type of a variant with the VT_BSTR type, SysFreeString is called on the contained string.
Of course the size of a regex has nothing to do with its performance.. FWIW I do use regex when they're the right tool for the job - and I have a registered Expresso install on 4 machines, and a regex analyzer feature in my VBIDE add-in OSS project. I don't hate regex. But I use a screwdriver for screws and a hammer for nails. If String.split gets it done, a regex is not warranted. — Mat's Mug22 secs ago
Reminds me of that "I know regex!" XKCD
"I suggest expanding your horizon with regex tools" ...seriously
eh, I think I'm just semi-subconsciously trying to get you to review & fix that PR so it can be merged... I don't want it to remain open for another week like the previous one
@Hosch250 that's me. I thought we could possibly streamline the tests with a somewhat standardized set of inputs that we could reuse... might not have been a stellar idea now that I read your arguments against it
@Comintern should be. The VBE would puke itself if we ran tests concurrently... And AssertHandler couldn't handle it either
@Comintern RD's reference collector already knows the control-specific properties that are exposed. But, for example, myUserForm.TextBox1 extends all of the Textbox properties and all/some of the IControl members (as per the table I posted).
@ThunderFrame Yeah, I was thinking that it might be possible to grab a different interface from it. F3 or whatever it is has to be decorating it with something, otherwise you couldn't pass them as Object or coerce them into a Variant.
@Mat'sMug OK - I'm looking for some generic API function that returns an allocated Variant of just just about anything that I can grab the memory allocation from. Should work if I never marshal the pointer...
^ Famous last words. If you don't hear from me in a while, it was a horrible crash.
I haven't found a control to test with, but MS anticipated that some control designers would implement member names that might clash with the IControl members. For example, if you had an ActiveX that exposed a Height property, then calling myUserForm.MyControl.Height would return the IControl.Height and myUserForm.myControl.Object.Height would return the control's Height member.
or, you could do:
Dim foo as myCustomControl 'or As Object
Set foo = myUserForm.myCustomControl
Debug.Print foo.Height
OK, so we just make a set of dummy interface Declaration, and "attach" to them when we resolve controls. Call QueryInterface, find out what interfaces it supports, then copy member specific Declaration for the control in question. VBA wants to run-time resolve them? Fine. We'll do the same thing.
That's why the ListView4.BoundControl is special/problematic. In the case of a ListView4 control, a ListView4 doesn't have a BoundValue property of its own, and nor does IControl seemingly extend BoundControl to a non-MSForms control. but if a custom control did have a BoundValue member, then it would be reachable as long as you weren't coding against an IControl instance.
That may just be a matter of where you're requesting an interface from. An IDispatch pointer can be specific to a parent interface. If we get the IUnknown, we can just ask the damned thing "what interfaces can I cast you to".
I have no clue why this didn't occur to me months ago. That's how COM is supposed to work.
@Comintern Access a control using FormName.ControlName.MemberName and you get IControl members and the control's members. Same if you use FormName.Controls("ControlName").MemberName.
Right, but it depends on which IDispatch it's returning. Remember that IDispatch is a parent interface that lies in front of the derived interface in a vtable.
If an object supports 4 interfaces, whatever container it's in can basically feed you any of the 4 IDispatches that it wants.
All of them should point back to the same GetIDsOfNamesimplementation, but the members might very well not be available on any specific interface
but, if you Dim x As ControlType, or Dim x As Object, then Set x = FormName.ControlName, then you typically only get the non-hidden members of the ControlType
But... since they are 4 different vtables, any one of them could return different members for the same object, especially if they're being extended by a container that hosts them.
@Comintern Yes, but it seems VBA is extending individual, built-in MSForms controls with some/all of the IControl members, depending upon the control. For Custom controls (i.e. everything not defined in MSForms), it exposes a fixed set of members.
so we still need to special case the MSForms controls
RD should know that accessing the Default (member namedDefault, not member with disp_id = 0), of a control is a run-time error for everything except a CommandButton
Wait does that mean we could connect the dots between Range and Range.Value? Because ATM the best we have is Range._Default being the default property of a Range
Just ̶t̶h̶i̶n̶k̶i̶n̶g̶ typing out loud here... If we know the size of a pointer on the platform and the number of members on an interface, we could marshal the pointer into an array and have access to the vtable...
♫ Woke up this morning, from the strangest dream I was in the biggest VBA project, The world has ever seen We were marching as one, on the road to the holy grail ♫
5
@Comintern yep, but couldn't help the band reference
> Methods may return an instance of [ValueTask<TResult>] when it's likely that the result of their operations will be available synchronously and when the method is expected to be invoked so frequently that the cost of allocating a new Task<TResult> for each call will be prohibitive.
From the API docs (emphasis added):
Methods may return an instance of this value type when it's likely that the result of their operations will be available synchronously and when the method is expected to be invoked so frequently that the cost of allocating a new Task<TResult> for each call ...
We have a few places in RD that would benefit from that, although I can't think of any off-hand.
@Hosch250 because it's not "built-in" - it's anything coming from any referenced library. the initial implementation was too naive, there was user stuff and then "built-in" stuff, which was all hard-coded
@Hosch250 ideally undeclared stuff should go in as soon as possible; some inspections just recently started picking them up. use meaningful name comes to mind
One more reason why I think we should get an 'Inspecting` state, which should have the refresh button activated, is that atm the user has no idea whether the inspections are still running or not.
I think, when we finally trigger the inspections from the ParseCoordinator, we should allow to pass a flag to the ParseCoordinator, possibly via the event args of the ParseRequestedevent, that indicates that the inspections do not have to run.
Running the inspections after a refactoring, inparticular during the ExtractMethodrefactoring, does not seem to be too useful.
In both cases, we have to change all inspections, but with the interface in between, we never have to do it again when we want to change the data passed to the inspections.
You directly query the declarations from the state. So, what the inspections see is direclty dependent on what we save in the state. There is no way to trim down what declartions the inspections see without changing them.
I've seen enough instances of collections of declarations being passed around to callees that expect a different set that I don't want to go that route.
I've seen some expecting only collections of user-defined declarations, and some that only want declarations of a certain declaration type (say, variables)...
It always seems to work best if you just pass the state in and let it work off that.
That interface was supposed to have functions for these different functionalities of the DeclarationFinder, basically of all the inspections use. (That is why I said that I would have to look at the inspections to determin what would be on the interface.) The basic implementation would just forward to the DeclarationFinder on the state. BTW, all but the inspections using parse tree listeners should actually run off the DeclarationFinder; it caches everything in suitable dictionaries.