Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2018-12

Bug on CodeTools to find unit using in `../path/unit.pas`

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marcos Douglas B. Santos

Hi,
I'm playing around with units to include them in a "different" way in a test program. I realized that there are some issues only on Lazarus IDE code-completion — no error to compile.

Inside the folder of the project, I've added a new unit in `msg` folder: `msg/msg.pas`.

If I use this unit on lpr using `in`, like this:
===begin===
program1;
uses
{...},

  `msg in 'msg/msg.pas'`;

===end===

...I have no issues to compile.
Pay attention that I haven't put `msg` folder on Search Path.

Inside on `msg` unit I have a code for testing:
function MakeString: string;

If uses that unit in any units on that program and try to code-complete "MakeS*" (Ctrl+SPACE) I got "Error: unit not found: msg" from CodeTools.

Lazarus 1.9.0 r58537 FPC 3.1.1 i386-win32-win32/win64

You can argue that I just need to include the path on Search Path but, please, don't. I want to use something like "dynamic paths".

Continuing the test, if I use that unit as `msg in 'msg/msg.pas' on the other units, I got no error from CodeTools:
===begin===
unit Unit1;
// a unit that has a Form, for example
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,

  msg in 'msg/msg.pas';

===end===

Which tells us that CodeTools knows how to read the "in 'path/unit'", but only if it was declared on the same unit that is using it.

So, I can use the path on all units but as the compiler knows how to compile if I just put one declaration on the lpr, using the same indentifier `msg` in all program, I believe the IDE should know how to read this too.

Am I right?

Best regards,
Marcos Douglas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20181208/19e394d5/attachment.html>

Reply by email

Mattias Gaertner
to Marcos Douglas B. Santos

On Sat, 8 Dec 2018 14:15:20 -0200
"Marcos Douglas B. Santos via lazarus"

Show quoted text 30 lines
Hi, I'm playing around with units to include them in a "different" way in a test program. I realized that there are some issues only on Lazarus IDE code-completion — no error to compile. Inside the folder of the project, I've added a new unit in `msg` folder: `msg/msg.pas`. If I use this unit on lpr using `in`, like this: ===begin=== program1; uses {...}, `msg in 'msg/msg.pas'`; ===end=== ...I have no issues to compile. Pay attention that I haven't put `msg` folder on Search Path. Inside on `msg` unit I have a code for testing: function MakeString: string; If uses that unit in any units on that program and try to code-complete "MakeS*" (Ctrl+SPACE) I got "Error: unit not found: msg" from CodeTools. Lazarus 1.9.0 r58537 FPC 3.1.1 i386-win32-win32/win64 You can argue that I just need to include the path on Search Path but, please, don't. I want to use something like "dynamic paths".

Can you add 'msg' to the Project / Compiler Options / Other Sources?

Show quoted text 12 lines
Continuing the test, if I use that unit as `msg in 'msg/msg.pas' on the other units, I got no error from CodeTools: ===begin=== unit Unit1; // a unit that has a Form, for example uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, msg in 'msg/msg.pas'; ===end=== Which tells us that CodeTools knows how to read the "in 'path/unit'", but only if it was declared on the same unit that is using it.

Correct.

Show quoted text 6 lines
So, I can use the path on all units but as the compiler knows how to compile if I just put one declaration on the lpr, using the same indentifier `msg` in all program, I believe the IDE should know how to read this too. Am I right?

Yes.
But this is not implemented yet.

Mattias

Reply by email

Marcos Douglas B. Santos
to Mattias Gaertner
PM Mattias Gaertner wrote 9 lines
On Sat, 8 Dec 2018 14:15:20 -0200 "Marcos Douglas B. Santos via lazarus" wrote: [...] > You can argue that I just need to include the path on Search Path but, > please, don't. I want to use something like "dynamic paths". Can you add 'msg' to the Project / Compiler Options / Other Sources?

Instead, can I add it on Search Path but using a macro or custom definition, to get the path accordingly to Build Mode choose?

best regards,
Marcos Douglas

Reply by email

Juha Manninen
to Marcos Douglas B. Santos
PM Marcos Douglas B. Santos wrote
Instead, can I add it on Search Path but using a macro or custom definition, to get the path accordingly to Build Mode choose?

Why?
The "Other unit files (-Fu)" setting is part of Build Modes. You can set a different path for each Build Mode.

Juha

Reply by email

Marcos Douglas B. Santos
to Juha Manninen
PM Juha Manninen wrote 9 lines
On Sun, Dec 9, 2018 at 2:06 PM Marcos Douglas B. Santos via lazarus wrote: > Instead, can I add it on Search Path but using a macro or custom > definition, to get the path accordingly to Build Mode choose? Why? The "Other unit files (-Fu)" setting is part of Build Modes. You can set a different path for each Build Mode.

Indeed. I've answered quickly without thinking properly. Sorry.

However, this do not solve "my problem", which is not use Search Paths. Why? I'll try to explain:
When I realized that I can use paths in uses clauses I thought that I could use `alias for units`, which is better than "namespaces", IMHO.

So, using my example before, I could do that:
uses

  `MyMsg in 'msg/msg.pas'`;

I just choose a new name for the file `msg.pas`, which is `MyMsg`. It compiles. I can use it as a prefix, eg., `MyMsg.AFunction()`, and it is great.
But if you put the `msg` folder in Search Path, the compiler will use the same file name as the unit, ie, the identifier will be the same: Msg.
Then I thought: If I "register" the name what I want for `msg.pas` on project (lpr), the compiler will use it in all code. However, as I've explained before, it doesn't work on IDE, having some issues on CodeTools.
Then I thought: I could use the path on each uses clause, no problem. If I need to change some path, I could just do a replace in all files
- no big deal. But, I discovered that I cannot use different `alias` pointing to the same file, because there are some issues about classes and interfaces.
For example:
unit A;
uses msg1 in 'msg/msg.pas'
-----
unit B;
uses msg2 in 'msg/msg.pas'

As I understood, when the compiler knows about `msg.pas`, it will use the first identifier that appeared, which is `msg1`. And that is a problem. Why?
Consider that:

unit strings;
type
  TStr = type string;
end;
---
unit b;
uses str in 'abc.strings.pas';
type
  IBar = interface
    procedure Exec(const s: TStr);
  end;
end;
---
unit c;
uses abcstr in 'abc.strings.pas';
type
  TBar = interface
    procedure Exec(const s: TStr);
  end;
end;

So, units B and C uses A, which has a `TStr` type declared. The problem here is that `IBar` is using `TStr` as `str.TStr` implicit; on C unit, `TBar` is using `TStr` as `abcstr.TStr`, and I have a compiler error.
As I understand, the compiler uses units as prefix for types.

Finally, it turn back us for the original issue: if I can "register" just one `alias` for an unit on the project (lpr), I could use it on all code of my project, in theory.
And why this is "important"?
If I have an unit like "Some.Long.Name.Unit", I will could use it like:

  foo in 'path/Some.Long.Name.Unit.pas';

And I've discovered another issue on IDE:
If I use like above `foo in 'path/Some.Long.Name.Unit.pas';`, IDE will save on XML project files the unit as `Some.Long.Name.Unit`, when it should be `foo` as the name of the unit.

best regards,
Marcos Douglas

Reply by email

Mattias Gaertner
to Marcos Douglas B. Santos

On Sun, 9 Dec 2018 22:33:47 -0200
"Marcos Douglas B. Santos via lazarus"

Show quoted text 10 lines
[...] unit A; uses msg1 in 'msg/msg.pas' ----- unit B; uses msg2 in 'msg/msg.pas' As I understood, when the compiler knows about `msg.pas`, it will use the first identifier that appeared, which is `msg1`. And that is a problem. Why?

For better chance of getting an answer you can ask the fpc developers on the fpc list.

Note that the 'in' feature came from Delphi, where it is used to mark which unit belongs to the project/package. And in Delphi the unitname must match.
FPC extended it to allow alias, but afaik it is hardly used.

Show quoted text 5 lines
[...] And I've discovered another issue on IDE: If I use like above `foo in 'path/Some.Long.Name.Unit.pas';`, IDE will save on XML project files the unit as `Some.Long.Name.Unit`, when it should be `foo` as the name of the unit.

That is the cached name of the unit name from its source, not some alias name. The IDE does not yet support alias names. Only a few functions support the 'in' alias.

Mattias

Reply by email

Marcos Douglas B. Santos
to Mattias Gaertner
AM Mattias Gaertner wrote 22 lines
On Sun, 9 Dec 2018 22:33:47 -0200 "Marcos Douglas B. Santos via lazarus" wrote: >[...] > unit A; > uses msg1 in 'msg/msg.pas' > ----- > unit B; > uses msg2 in 'msg/msg.pas' > > As I understood, when the compiler knows about `msg.pas`, it will use > the first identifier that appeared, which is `msg1`. And that is a > problem. Why? For better chance of getting an answer you can ask the fpc developers on the fpc list. Note that the 'in' feature came from Delphi, where it is used to mark which unit belongs to the project/package. And in Delphi the unitname must match.

Indeed, you're right. I've tested and it doesn't work, at least on Delphi 7.

FPC extended it to allow alias, but afaik it is hardly used.

It could be a great feature for both compilers, IMHO.

Show quoted text 9 lines
>[...] > And I've discovered another issue on IDE: > If I use like above `foo in 'path/Some.Long.Name.Unit.pas';`, IDE will > save on XML project files the unit as `Some.Long.Name.Unit`, when it > should be `foo` as the name of the unit. That is the cached name of the unit name from its source, not some alias name. The IDE does not yet support alias names. Only a few functions support the 'in' alias.

I got it, thanks.

Marcos Douglas

Reply by email