fix #230 - DUB project dependencies not available in completion anymore

This commit is contained in:
Basile Burg 2018-02-06 16:00:31 +01:00
parent 7957c991d3
commit 7ff81260ea
4 changed files with 212 additions and 38 deletions

View File

@ -323,8 +323,6 @@ constructor TCED2SynPresetsLoaderForm.Create(AOwner: TComponent);
var var
fname: string; fname: string;
pnl: TPanel; pnl: TPanel;
btn: TBitBtn;
isc: TIconScaledSize;
begin begin
inherited; inherited;
fBackup:= TCED2SynPreset.Create(nil); fBackup:= TCED2SynPreset.Create(nil);

View File

@ -8,7 +8,7 @@ uses
Classes, SysUtils, fpjson, jsonparser, jsonscanner, process, strutils, Classes, SysUtils, fpjson, jsonparser, jsonscanner, process, strutils,
LazFileUtils, RegExpr, LazFileUtils, RegExpr,
ce_common, ce_interfaces, ce_observer, ce_dialogs, ce_processes, ce_common, ce_interfaces, ce_observer, ce_dialogs, ce_processes,
ce_writableComponent, ce_compilers; ce_writableComponent, ce_compilers, ce_semver, ce_stringrange;
type type
@ -20,6 +20,26 @@ type
TDubArchOverride = (auto, x86, x86_64); TDubArchOverride = (auto, x86, x86_64);
PDubLocalPackage = ^TDubLocalPackage;
TDubLocalPackage = record
name : string;
versions: array of TSemVer;
procedure addVersion(const value: string);
function findVersion(constref value: TSemVer): boolean;
end;
TDubLocalPackages = class
strict private
fRoot: string;
fLocalPackages: array of TDubLocalPackage;
public
procedure update;
function find(const name: string; out package: PDubLocalPackage): boolean;
function fetch(constref version: TSemVer): PDubLocalPackage;
function getPackageePath(package: PDubLocalPackage): string;
end;
(** (**
* Stores the build options, always applied when a project is build * Stores the build options, always applied when a project is build
*) *)
@ -95,7 +115,7 @@ type
fSaveAsUtf8: boolean; fSaveAsUtf8: boolean;
fCompiled: boolean; fCompiled: boolean;
fMsgs: ICEMessagesDisplay; fMsgs: ICEMessagesDisplay;
// fLocalPackages: TDubLocalPackages;
procedure doModified; procedure doModified;
procedure updateFields; procedure updateFields;
procedure updatePackageNameFromJson; procedure updatePackageNameFromJson;
@ -191,6 +211,125 @@ const
DubDefaultConfigName = '(default config)'; DubDefaultConfigName = '(default config)';
{$REGION TDubLocalPackages -----------------------------------------------------}
procedure TDubLocalPackage.addVersion(const value: string);
var
v: TSemVer;
i: integer;
begin
if value = 'vmaster' then
v.init('v0.0.0-master')
else try
v.init(value);
except
exit;
end;
for i:= 0 to high(versions) do
begin
if versions[i] = v then
exit;
end;
setLength(versions, length(versions) + 1);
versions[high(versions)] := v;
end;
function TDubLocalPackage.findVersion(constref value: TSemVer): boolean;
var
i: integer;
begin
result := false;
for i:= 0 to high(versions) do
if versions[i] = value then
exit(true);
end;
procedure TDubLocalPackages.update;
var
p: TStringList;
s: string;
n: string;
v: string = '';
i: integer;
j: integer = 0;
d: PDubLocalPackage = nil;
h: TStringRange = (ptr: nil; pos: 0; len: 0);
begin
setLength(fLocalPackages, 0);
{$IFDEF WINDOWS}
fRoot := GetEnvironmentVariable('APPDATA') + '\dub\packages\';
{$ELSE}
fRoot := GetEnvironmentVariable('HOME') + '/.dub/packages/';
{$ENDIF}
if not fRoot.dirExists then
exit;
p := TStringList.Create;
try
listFolders(p, fRoot);
for i := 0 to p.Count-1 do
begin
j := 0;
s := p[i];
h.init(s);
while true do
begin
h.popUntil('-');
if h.empty then
break;
if (h.popFront^.front in ['0'..'9']) or
h.endsWith('master') then
begin
j := h.position;
break;
end;
end;
if (j = 0) then
continue;
n := s[1..j-1];
n := n.extractFileName;
if not find(n, d) then
begin
setLength(fLocalPackages, length(fLocalPackages) + 1);
d := @fLocalPackages[high(fLocalPackages)];
d^.name := n;
end;
v := 'v' + s[j+1 .. length(s)];
d^.addVersion(v);
end;
finally
p.Free;
end;
end;
function TDubLocalPackages.find(const name: string; out package: PDubLocalPackage): boolean;
var
i: integer;
begin
result := false;
package:= nil;
for i := 0 to high(fLocalPackages) do
if fLocalPackages[i].name = name then
begin
result := true;
package := @fLocalPackages[i];
break;
end;
end;
function TDubLocalPackages.fetch(constref version: TSemVer): PDubLocalPackage;
begin
result := nil;
end;
function TDubLocalPackages.getPackageePath(package: PDubLocalPackage): string;
begin
result := fRoot + package^.name;
end;
{$ENDREGION}
{$REGION Options ---------------------------------------------------------------} {$REGION Options ---------------------------------------------------------------}
procedure TCEDubBuildOptionsBase.setLinkMode(value: TDubLinkMode); procedure TCEDubBuildOptionsBase.setLinkMode(value: TDubLinkMode);
begin begin
@ -336,12 +475,15 @@ begin
fImportPaths := TStringList.Create; fImportPaths := TStringList.Create;
fImportPaths.Sorted:=true; fImportPaths.Sorted:=true;
fImportPaths.Duplicates:=dupIgnore; fImportPaths.Duplicates:=dupIgnore;
//
json.Add('name', ''); json.Add('name', '');
endModification; endModification;
subjProjNew(fProjectSubject, self); subjProjNew(fProjectSubject, self);
doModified; doModified;
fModified:=false; fModified:=false;
fLocalPackages := TDubLocalPackages.Create;
fLocalPackages.update;
end; end;
destructor TCEDubProject.destroy; destructor TCEDubProject.destroy;
@ -349,12 +491,13 @@ begin
killProcess(fDubProc); killProcess(fDubProc);
subjProjClosing(fProjectSubject, self); subjProjClosing(fProjectSubject, self);
fProjectSubject.free; fProjectSubject.free;
//
fJSON.Free; fJSON.Free;
fBuildTypes.Free; fBuildTypes.Free;
fConfigs.Free; fConfigs.Free;
fSrcs.Free; fSrcs.Free;
fImportPaths.Free; fImportPaths.Free;
fLocalPackages.Free;
inherited; inherited;
end; end;
{$ENDREGION --------------------------------------------------------------------} {$ENDREGION --------------------------------------------------------------------}
@ -1019,55 +1162,65 @@ procedure TCEDubProject.updateImportPathsFromJson;
// see TCEDcdWrapper.projChanged() // see TCEDcdWrapper.projChanged()
procedure addDepsFrom(obj: TJSONObject); procedure addDepsFrom(obj: TJSONObject);
var var
folds: TStringList;
deps: TJSONObject; deps: TJSONObject;
pth: string; pck: PDubLocalPackage;
str: string; j: TJSONData;
i,j,k: integer; p: string;
s: string;
v: string;
n: string;
o: string;
z: string;
r: TStringRange = (ptr: nil; pos: 0; len: 0);
q: TSemVer;
i: integer;
begin begin
if obj.findObject('dependencies', deps) then if obj.findObject('dependencies', deps) then
begin begin
{$IFDEF WINDOWS} {$IFDEF WINDOWS}
pth := GetEnvironmentVariable('APPDATA') + '\dub\packages\'; z := GetEnvironmentVariable('APPDATA') + '\dub\packages\';
{$ELSE} {$ELSE}
pth := GetEnvironmentVariable('HOME') + '/.dub/packages/'; z := GetEnvironmentVariable('HOME') + '/.dub/packages/';
{$ENDIF} {$ENDIF}
folds := TStringList.Create; for i := 0 to deps.Count-1 do
listFolders(folds, pth); begin
try n := deps.Names[i];
// remove semver from folder names s := z + n;
for i := 0 to folds.Count-1 do if fLocalPackages.find(n, pck) then
begin begin
str := folds[i]; j := deps.Items[i];
k := -1; if j.JSONType <> TJSONtype.jtString then
for j := 1 to length(str) do continue;
if str[j] = '-' then
k := j; v := j.AsString;
if k <> -1 then r.init(v);
folds[i] := str[1..k-1] + '=' + str[k .. length(str)]; o := r.takeUntil(['0'..'9']).yield;
end; p := r.takeUntil(#0).yield;
// add as import if names match if p = 'master' then
for i := 0 to deps.Count-1 do q.init('v0.0.0-master')
begin else
str := pth + deps.Names[i]; q.init('v' + p);
if folds.IndexOfName(str) <> -1 then
if fLocalPackages.find(n, pck) and
pck^.findVersion(q) then
begin begin
if (str + folds.Values[str] + DirectorySeparator + 'source').dirExists then p := s + '-' + p + DirectorySeparator + n + DirectorySeparator;
fImportPaths.Add(str + DirectorySeparator + 'source') if (p + 'source').dirExists then
else if (str + folds.Values[str] + DirectorySeparator + 'src').dirExists then fImportPaths.Add(p + 'source')
fImportPaths.Add(str + DirectorySeparator + 'src'); else if (p + 'src').dirExists then
fImportPaths.Add(p + 'src');
end; end;
end; end;
finally
folds.Free;
end; end;
end; end;
end; end;
var var
conf: TJSONObject; conf: TJSONObject;
begin begin
if fJSON.isNil then exit; if fJSON.isNil then
// exit;
addFrom(fJSON); addFrom(fJSON);
addDepsFrom(fJSON); addDepsFrom(fJSON);
conf := getCurrentCustomConfig; conf := getCurrentCustomConfig;

View File

@ -177,6 +177,11 @@ begin
assert(v2.major = 0); assert(v2.major = 0);
assert(v2.minor = 0); assert(v2.minor = 0);
assert(v2.patch = 2060); assert(v2.patch = 2060);
v1.init('v0.6.0');
assert(v1.major = 0);
assert(v1.minor = 6);
assert(v1.patch = 0);
{$ENDIF} {$ENDIF}
end. end.

View File

@ -58,6 +58,7 @@ type
// resets the range. // resets the range.
function reset: PStringRange; {$IFNDEF DEBUG}inline;{$ENDIF} function reset: PStringRange; {$IFNDEF DEBUG}inline;{$ENDIF}
// advances the range while the front is in value, returns a copy. // advances the range while the front is in value, returns a copy.
function takeWhile(value: TSysCharSet): TStringRange; overload; {$IFNDEF DEBUG}inline;{$ENDIF} function takeWhile(value: TSysCharSet): TStringRange; overload; {$IFNDEF DEBUG}inline;{$ENDIF}
// advances the range while the front is equal to value, returns a copy. // advances the range while the front is equal to value, returns a copy.
@ -96,6 +97,12 @@ type
implementation implementation
{$IFDEF DEBUG}
var
t1: string;
r1: TStringRange;
{$ENDIF}
class function TStringRange.create(const str: string): TStringRange; class function TStringRange.create(const str: string): TStringRange;
begin begin
result.ptr := nil; result.ptr := nil;
@ -339,5 +346,16 @@ begin
Result := ptr[pos .. length(value)-1] = value; Result := ptr[pos .. length(value)-1] = value;
end; end;
{$IFDEF DEBUG}
begin
t1 := '~>0.6.0';
r1.init(t1);
assert(r1.takeUntil(['0'..'9']).yield = '~>');
assert(r1.takeUntil(#0).yield = '0.6.0');
t1 := '>=0.8.0-alpha.1';
r1.init(t1);
assert(r1.takeUntil(['0'..'9']).yield = '>=');
assert(r1.takeUntil(#0).yield = '0.8.0-alpha.1');
{$ENDIF}
end. end.