IDE: Handle the selection lists for all compiler options in the parser. Change some lists into groups.

git-svn-id: trunk@42365 -
This commit is contained in:
juha 2013-08-06 11:59:42 +00:00
parent c518a5eec2
commit a5448a50c8
2 changed files with 130 additions and 72 deletions

View File

@ -232,19 +232,6 @@ var
FGeneratedControls.Add(Lbl);
end;
procedure AddChoices(aComboBox: TComboBox; aCategory: string);
// Add selection choices to ComboBox from data originating from "fpc -i".
var
i: Integer;
begin
with FOptionsReader.SupportedCategories do
if Find(aCategory, i) then
aComboBox.Items.Assign(Objects[i] as TStrings)
else
raise Exception.CreateFmt('AddChoices: Selection list for "%s" is not found.',
[aCategory]);
end;
procedure RenderOneLevel(aParentGroup: TCompilerOptGroup);
var
Cntrl, Lbl: TControl;
@ -286,18 +273,8 @@ var
Cntrl := MakeEditCntrl(Lbl, TComboBox);
cb := TComboBox(Cntrl);
cb.Style := csDropDownList;
// ToDo: Move this logic to parser data so values can be validated better.
case Opt.Option of
'-Ca': AddChoices(cb, 'ABI targets:');
'-Cf': AddChoices(cb, 'FPU instruction sets:');
'-Cp': AddChoices(cb, 'CPU instruction sets:');
'-Oo[NO]': AddChoices(cb, 'Optimizations:');
'-Op': AddChoices(cb, 'CPU instruction sets:');
'-OW': AddChoices(cb, 'Whole Program Optimizations:');
'-Ow': AddChoices(cb, 'Whole Program Optimizations:');
else
raise Exception.Create('AddChoices: Unknown option ' + Opt.Option);
end;
if Assigned(Opt.Choices) then
cb.Items.Assign(Opt.Choices);
cb.Text := Opt.Value;
cb.OnChange := @ComboChange;
MakeDescrLabel(Cntrl, LeftDescrEdit);

View File

@ -102,9 +102,12 @@ type
fOwnerGroup: TCompilerOptGroup;
fVisible: Boolean; // Used for filtering.
fIgnored: Boolean; // Pretend this option does not exist.
fChoices: TStrings; // Choices got from "fpc -i"
procedure AddChoices(aCategory: string);
procedure Filter(aFilter: string; aOnlySelected: Boolean);
protected
procedure ParseOption(aDescr: string; aIndent: integer); virtual;
procedure ParseEditKind; virtual;
procedure ParseOption(aDescr: string; aIndent: integer);
public
constructor Create(aOwnerGroup: TCompilerOptGroup);
destructor Destroy; override;
@ -119,6 +122,7 @@ type
property Indentation: integer read fIndentation;
property Visible: Boolean read fVisible write fVisible;
property Ignored: Boolean read fIgnored write fIgnored;
property Choices: TStrings read fChoices;
end;
TCompilerOptList = TObjectList;
@ -131,7 +135,7 @@ type
// List of options belonging to this group.
fCompilerOpts: TCompilerOptList;
protected
procedure ParseOption(aDescr: string; aIndent: integer); override;
procedure ParseEditKind; override;
public
constructor Create(aOwnerGroup: TCompilerOptGroup);
destructor Destroy; override;
@ -147,12 +151,11 @@ type
// A set of options. A combination of chars or numbers following the option char.
TCompilerOptSet = class(TCompilerOptGroup)
private
fHasNumber: Boolean;
function SetNumberOpt(aValue: string): Boolean;
function SetBooleanOpt(aValue: string): Boolean;
protected
procedure AddOptions(aDescr: string; aIndent: integer);
procedure ParseOption(aDescr: string; aIndent: integer); override;
procedure ParseEditKind; override;
public
constructor Create(aOwnerGroup: TCompilerOptGroup);
destructor Destroy; override;
@ -176,7 +179,7 @@ type
fCompilerVersion: string; // Parsed from "fpc -h".
fErrorMsg: String;
procedure ReadVersion(s: string);
//function FindPrevGroup(aIndent: integer): TCompilerOptGroup;
procedure AddGroupItems(aGroup: TCompilerOptGroup; aItems: TStrings);
function ParseI(aLines: TStringList): TModalResult;
function ParseH(aLines: TStringList): TModalResult;
public
@ -199,6 +202,8 @@ type
implementation
var
CurrentCategories: TStringList; // To pass categories to options parser.
{ TCompiler }
@ -382,6 +387,26 @@ begin
Result := aOpt[2] in ['i', 'F', 'e', 'o', 'd', 'u', 'M', 'T'];
end;
function IsGroup(aOpt: string; var aCategoryList: TStrings): Boolean;
// This option should be a group instead of a selection list.
var
i: Integer;
Category: string;
begin
if AnsiStartsStr('-Oo', aOpt) then
Category := 'Optimizations:'
else if AnsiStartsStr('-OW', aOpt) or AnsiStartsStr('-Ow', aOpt) then
Category := 'Whole Program Optimizations:'
;
Result := Category <> '';
if Result then
if CurrentCategories.Find(Category, i) then
aCategoryList := CurrentCategories.Objects[i] as TStrings
else
raise Exception.CreateFmt('No list of options found for "%s".', [Category]);
end;
{ TCompilerOpt }
constructor TCompilerOpt.Create(aOwnerGroup: TCompilerOptGroup);
@ -398,39 +423,71 @@ begin
inherited Destroy;
end;
procedure TCompilerOpt.ParseOption(aDescr: string; aIndent: integer);
procedure TCompilerOpt.AddChoices(aCategory: string);
// Add selection choices for this option. Data originates from "fpc -i".
var
i, Start: Integer;
i: Integer;
begin
if CurrentCategories.Find(aCategory, i) then
fChoices := CurrentCategories.Objects[i] as TStrings
else
raise Exception.CreateFmt('No selection list for "%s" found.', [aCategory]);
end;
procedure TCompilerOpt.ParseEditKind;
begin
fIndentation := aIndent;
// Separate the actual option and description from each other
Start := aIndent+1;
if (Length(aDescr) < aIndent) or (aDescr[Start] <> '-') then
raise Exception.Create('Option description does not start with "-"');
i := Start;
while (i < Length(aDescr)) and (aDescr[i] <> ' ') do
Inc(i);
fOption := Copy(aDescr, Start, i-Start);
while (i < Length(aDescr)) and (aDescr[i] = ' ') do
Inc(i);
fDescription := Copy(aDescr, i, Length(aDescr));
// Guess whether this option can be edited and what is the EditKind
fEditKind := oeBoolean; // Default kind
i := Length(fOption);
if (i > 3) and (fOption[i-2] = '<') and (fOption[i] = '>') then
begin
case fOption[i-1] of
if (Length(fSuffix) = 3) and (fSuffix[1] = '<') and (fSuffix[3] = '>') then
case fSuffix[2] of
'x': fEditKind:=oeText; // <x>
'n': fEditKind:=oeNumber; // <n>
end;
if Pos('fpc -i', fDescription) > 0 then
begin
fEditKind := oeList; // Values will be got later.
case fOption of
'-Ca': AddChoices('ABI targets:');
'-Cf': AddChoices('FPU instruction sets:');
'-Cp': AddChoices('CPU instruction sets:');
// '-Oo', '-Oo[NO]': AddChoices('Optimizations:');
'-Op': AddChoices('CPU instruction sets:');
// '-OW': AddChoices('Whole Program Optimizations:');
// '-Ow': AddChoices('Whole Program Optimizations:');
else
raise Exception.Create('Don''t know where to get selection list for option '+fOption);
end;
end;
end;
procedure TCompilerOpt.ParseOption(aDescr: string; aIndent: integer);
var
i: Integer;
begin
fIndentation := aIndent;
// Separate the actual option and description from each other
if aDescr[1] <> '-' then
raise Exception.Create('Option description does not start with "-"');
i := 1;
while (i < Length(aDescr)) and (aDescr[i] <> ' ') do
Inc(i);
fOption := Copy(aDescr, 1, i-1);
while (i < Length(aDescr)) and (aDescr[i] = ' ') do
Inc(i);
fDescription := Copy(aDescr, i, Length(aDescr));
i := Length(fOption);
if (i > 3) and (fOption[i-2] = '<') and (fOption[i] = '>') then
begin
// Move <x> in the end to Suffix. We need the pure option later.
fSuffix := Copy(fOption, i-2, i);
fOption := Copy(fOption, 1, i-3);
i := Length(fOption);
if Copy(fOption, i-3, 4) = '[NO]' then
SetLength(fOption, i-4);
end;
if Pos('fpc -i', fDescription) > 0 then
fEditKind := oeList; // Values will be got later.
if fOwnerGroup.fIgnored or IsIgnoredOption(fOption) then
fIgnored := True;
ParseEditKind;
end;
procedure TCompilerOpt.Filter(aFilter: string; aOnlySelected: Boolean);
@ -582,9 +639,8 @@ begin
Result := Assigned(Opt);
end;
procedure TCompilerOptGroup.ParseOption(aDescr: string; aIndent: integer);
procedure TCompilerOptGroup.ParseEditKind;
begin
inherited ParseOption(aDescr, aIndent);
fEditKind := oeGroup;
end;
@ -698,7 +754,6 @@ procedure TCompilerOptSet.AddOptions(aDescr: string; aIndent: integer);
OptSet.fOption := 'Number';
OptSet.fDescription := aDescr;
OptSet.fEditKind := oeSetNumber;
fHasNumber := True;
end;
procedure NewSetElem(aDescr: string);
@ -718,20 +773,21 @@ var
Opt1, Opt2: string;
i: Integer;
begin
Opt1 := Copy(aDescr, aIndent+1, Length(aDescr));
if AnsiStartsStr('<n>', Opt1) then
NewSetNumber(Opt1)
if AnsiStartsStr('<n>', aDescr) then
NewSetNumber(aDescr)
else begin
i := PosEx(':', Opt1, 4);
if (i > 0) and (Opt1[i-1]=' ') and (Opt1[i-2]<>' ') and (Opt1[i-3]=' ') then
i := PosEx(':', aDescr, 4);
if (i > 0) and (aDescr[i-1]=' ') and (aDescr[i-2]<>' ') and (aDescr[i-3]=' ') then
begin
// Found another option on the same line, like ' a :'
Opt2 := Copy(Opt1, i-2, Length(Opt1));
if Opt1[3] = ':' then
Opt1 := TrimRight(Copy(Opt1, 1, i-3))
Opt2 := Copy(aDescr, i-2, Length(aDescr));
if aDescr[3] = ':' then
Opt1 := TrimRight(Copy(aDescr, 1, i-3))
else
Opt1 := '';
end;
end
else
Opt1 := aDescr;
if Opt1 <> '' then // Can be empty when line in help output is split.
NewSetElem(Opt1)
else if fCompilerOpts.Count > 0 then
@ -741,9 +797,8 @@ begin
end;
end;
procedure TCompilerOptSet.ParseOption(aDescr: string; aIndent: integer);
procedure TCompilerOptSet.ParseEditKind;
begin
inherited ParseOption(aDescr, aIndent);
fEditKind := oeSet;
end;
@ -757,6 +812,8 @@ begin
fOtherOptions := TStringList.Create;
fSupportedCategories := TStringList.Create;
fRootOptGroup := TCompilerOptGroup.Create(Nil);
// Categories are passed to options parser through a global variable.
CurrentCategories := fSupportedCategories;
end;
destructor TCompilerOptReader.Destroy;
@ -833,6 +890,20 @@ begin
end;
end;
procedure TCompilerOptReader.AddGroupItems(aGroup: TCompilerOptGroup; aItems: TStrings);
var
Opt: TCompilerOpt;
i: Integer;
begin
for i := 1 to aItems.Count-1 do // Skip the first empty item.
begin
Opt := TCompilerOpt.Create(aGroup); // Add it under a group
Opt.fOption := aGroup.Option + aItems[i];
Opt.fIndentation := aGroup.Indentation+4;
Opt.fEditKind := oeBoolean;
end;
end;
function TCompilerOptReader.ParseH(aLines: TStringList): TModalResult;
const
OptSetId = 'a combination of';
@ -840,7 +911,8 @@ var
i, ThisInd, NextInd: Integer;
ThisLine, NextLine: String;
Opt: TCompilerOpt;
LastGroup: TCompilerOptGroup;
LastGroup, SubGroup: TCompilerOptGroup;
GroupItems: TStrings;
begin
Result := mrOK;
LastGroup := fRootOptGroup;
@ -848,12 +920,13 @@ begin
begin
ThisLine := StringReplace(aLines[i],'-Agas-darwinAssemble','-Agas-darwin Assemble',[]);
ThisInd := CalcIndentation(ThisLine);
ThisLine := Trim(ThisLine);
if ThisInd = 0 then
begin
ReadVersion(ThisLine); // Top header lines for compiler version etc.
Continue;
end;
if (Trim(ThisLine) = '') or (ThisInd > 30)
if (ThisLine = '') or (ThisInd > 30)
or (Pos(' -? ', ThisLine) > 0)
or (Pos(' -h ', ThisLine) > 0) then Continue;
@ -872,9 +945,9 @@ begin
// A hack to deal with split lined in the help output.
NextInd := ThisInd
else begin
if Pos(OptSetId, ThisLine) > 0 then // Header for sets
if Pos(OptSetId, ThisLine) > 0 then // Header for sets
LastGroup := TCompilerOptSet.Create(LastGroup)
else // Group header for options
else // Group header for options
LastGroup := TCompilerOptGroup.Create(LastGroup);
LastGroup.ParseOption(ThisLine, ThisInd);
end;
@ -882,14 +955,22 @@ begin
if NextInd <= ThisInd then
begin
// This is an option
if (LastGroup is TCompilerOptSet) then // Add it to a set (may add many)
if (LastGroup is TCompilerOptSet) then // Add it to a set (may add many)
TCompilerOptSet(LastGroup).AddOptions(ThisLine, ThisInd)
else begin
Opt := TCompilerOpt.Create(LastGroup); // Add it under a group
Opt.ParseOption(ThisLine, ThisInd);
if IsGroup(ThisLine, GroupItems) then
begin
SubGroup := TCompilerOptGroup.Create(LastGroup);
SubGroup.ParseOption(ThisLine, ThisInd);
AddGroupItems(SubGroup, GroupItems);
end
else begin
Opt := TCompilerOpt.Create(LastGroup); // Add it under a group
Opt.ParseOption(ThisLine, ThisInd);
end;
end;
if (NextInd <> -1) and (NextInd < ThisInd) then
LastGroup := LastGroup.fOwnerGroup; // Return to a previous group
LastGroup := LastGroup.fOwnerGroup; // Return to a previous group
end;
end;
end;