Because the methods can be used both ways:
type
TMyClass = class
public
class procedure Foo;
procedure Bar;
end;
class procedure TMyClass.Foo;
begin
WriteLn('Foo');
end;
procedure TMyClass.Bar;
begin
WriteLn('Bar');
end;
type
TMethodProcedure = procedure of object;
var
i: TMyClass;
p: TMethodProcedure;
m: TMethod;
begin
i:=TMyClass.Create;
i.Foo; // Calling class method from instance is perfectly valid
m.Code:=@TMyClass.Bar; // Taking the pointer of a method from the class is perfectly valid
m.Data:=i;
p:=TMethodProcedure(m);
p(); // Calling constructed TMethod function pointer is perfectly valid
end.
You can use ClassName.Method to get the pointer of a method, as a raw pointer to use in TMethod. Also you call call a class Method from an instance. Both are valid constructs, so Lazarus suggests both.
Also note that Lazarus tends to show more than FPC actually allows, because to do the error checking FPC does multiple passes, which require the whole context. Lazarus tries to give you suggestions even when the surrounding code is faulty, otherwise you would get error messages left and right when trying to use autocomplete.
So this is why Lazarus will show you those methods anyways, because they applicable in some circumstances, and filtering those out would be to restrictive. It's better to show more and have the user filter, instead of filtering to much and accidentally hiding something because the user made a mistake earlier on in the same line
I already hate it when Lazarus tries to be smart and only show functions that return something when on the right hand side of an assignment, because sometimes you vaguely remember there is another method, but it turns out that instead of having a return type, it uses a var param, so it is hidden. So even though Lazarus is correct in not showing this method because it's "wrong" on the right hand side of an assignment, I still want to see it, because I can just change the assignment to a call with a var parameter if I see that it is called differently.
I have a well functioning brain, so it should just show me everything that might be applicable and let me figure out how to deal with it
Also as a side note:
This is how the compiler works.
Lazarus is not the compiler, it is more leanient than the compiler, as most LSPs are as well, to allow typos while writing the code not effecting the utility. If you have a single typo most compilers will just quit, Lazarus tries to backtrack and continue with the next instruction anew to not have a single typo in a file ruin code completion in the rest of the file.
This is also the case in other languages, if I take the following code in C#:
class Test {
static void Foo( {
Test.F
}
}
The language tools will still offer me to complete to "Foo", even tho it is clearly not a valid construct and the actual compiler would never get this far because it's an LL(1) compiler that would not be able to recover from the incomplete parameter list.
I know exactly one language server which uses the same parser as the compiler and that the Haskell language server and it is awful for exactly that reason.
Second:
like F#
Most tooling actually behaves the same. I just checked for example with the Java LSP, and it works exactly the same. The Clang LSP for C++ also does the same showing static methods as function methods. I think with IntelliSense for F# and C# you probably just found the only LSP where this is
not the case.
And I would say this is because filtering out the static methods from the method list is a bad thing because it makes discovering the class much harder. So this is a fault of intellisense and a feature of Lazarus, the Java LSP and clangd rather than the other way around