1 {
2 ***************************************************************************
3 * *
4 * This source is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This code is distributed in the hope that it will be useful, but *
10 * WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * General Public License for more details. *
13 * *
14 * A copy of the GNU General Public License is available on the World *
15 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
16 * obtain it by writing to the Free Software Foundation, *
17 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
18 * *
19 ***************************************************************************
20
21 Author: Mattias: Gaertner
22
23 Abstract:
24 When a new unit is created check if compiler options in lpi and main source
25 differ. This is a common mistake when upgrading old projects.
26 }
27 unit CheckCompOptsForNewUnitDlg;
28
29 {$mode objfpc}{$H+}
30
31 interface
32
33 uses
34 Classes, SysUtils, LCLProc, FileUtil, Forms, Controls, Graphics, Dialogs,
35 StdCtrls, ExtCtrls, ButtonPanel,
36 CodeToolManager, BasicCodeTools, DefineTemplates,
37 CompOptsIntf, ProjectIntf, IDEDialogs,
38 InputHistory, TransferMacros, Project, LazarusIDEStrConsts;
39
40 type
41
42 { TCheckCompOptsForNewUnitDialog }
43
44 TCheckCompOptsForNewUnitDialog = class(TForm)
45 AnsistringCheckBox: TCheckBox;
46 ButtonPanel1: TButtonPanel;
47 DoNotWarnCheckBox: TCheckBox;
48 ModeComboBox: TComboBox;
49 ModeLabel: TLabel;
50 NoteLabel: TLabel;
51 procedure FormCreate(Sender: TObject);
52 procedure OkButtonClick(Sender: TObject);
53 private
54 FMainAnsistring: char;
55 FMainMode: string;
56 public
57 CompOpts: TLazCompilerOptions;
58 procedure UpdateOptions;
59 property MainMode: string read FMainMode write FMainMode;
60 property MainAnsistring: char read FMainAnsistring write FMainAnsistring;
61 end;
62
CheckCompOptsAndMainSrcForNewUnitnull63 function CheckCompOptsAndMainSrcForNewUnit(CompOpts: TLazCompilerOptions): TModalResult;
GetIgnorePathForCompOptsAndMainSrcDiffernull64 function GetIgnorePathForCompOptsAndMainSrcDiffer(CompOpts: TLazCompilerOptions): string;
65
66 implementation
67
CheckCompOptsAndMainSrcForNewUnitnull68 function CheckCompOptsAndMainSrcForNewUnit(CompOpts: TLazCompilerOptions): TModalResult;
69 var
70 ProjCompOpts: TProjectCompilerOptions;
71 MainUnit: TUnitInfo;
72 Src: String;
73 StartPos: Integer;
74 p: PChar;
75 Mode: String;
76 AnsistringMode: Char;
77 NestedComments: Boolean;
78 Dlg: TCheckCompOptsForNewUnitDialog;
79 IgnoreIdentifier: String;
80 begin
81 Result:=mrOK;
82 if CompOpts is TProjectCompilerOptions then
83 begin
84 ProjCompOpts:=TProjectCompilerOptions(CompOpts);
85 if (ProjCompOpts.LazProject=nil) then exit;
86 MainUnit:=ProjCompOpts.LazProject.MainUnitInfo;
87 if (MainUnit=nil) or (MainUnit.Source=nil) then exit;
88
89 // check if this question should be ignored
90 IgnoreIdentifier:=GetIgnorePathForCompOptsAndMainSrcDiffer(CompOpts);
91 if (IgnoreIdentifier<>'')
92 and (InputHistories.Ignores.Find(IgnoreIdentifier)<>nil) then
93 exit;
94
95 Src:=MainUnit.Source.Source;
96 Mode:='';
97 AnsistringMode:=#0;
98 StartPos:=1;
99 NestedComments:=false;
100 repeat
101 StartPos:=FindNextCompilerDirective(Src,StartPos,NestedComments);
102 if StartPos>length(Src) then break;
103 p:=@Src[StartPos];
104 StartPos:=FindCommentEnd(Src,StartPos,NestedComments);
105 if p^<>'{' then continue;
106 inc(p);
107 if p^<>'$' then continue;
108 inc(p);
109 if (Mode='') and (CompareIdentifiers(p,'mode')=0) then begin
110 // mode directive
111 inc(p,4);
112 while p^ in [' ',#9] do inc(p);
113 Mode:=GetIdentifier(p);
114 end
115 else if (AnsistringMode=#0) and (p^='H') and (p[1] in ['+','-']) then begin
116 // ansistring directive
117 AnsistringMode:=p[1];
118 end;
119 until false;
120 //debugln(['CheckCompOptsAndMainSrcForNewUnit Mode=',Mode,' ProjMode=',ProjCompOpts.SyntaxMode,' Str=',AnsistringMode='+',' ProjStr=',ProjCompOpts.UseAnsiStrings]);
121 if ((Mode<>'') and (SysUtils.CompareText(Mode,ProjCompOpts.SyntaxMode)<>0))
122 or ((AnsistringMode<>#0) and ((AnsistringMode='+')<>ProjCompOpts.UseAnsiStrings))
123 then begin
124 Dlg:=TCheckCompOptsForNewUnitDialog.Create(nil);
125 try
126 Dlg.CompOpts:=CompOpts;
127 Dlg.MainMode:=Mode;
128 Dlg.MainAnsistring:=AnsistringMode;
129 Dlg.UpdateOptions;
130 if Dlg.ShowModal<>mrOk then
131 Result:=mrCancel;
132 finally
133 Dlg.Free;
134 end;
135 end;
136 end;
137 end;
138
GetIgnorePathForCompOptsAndMainSrcDiffernull139 function GetIgnorePathForCompOptsAndMainSrcDiffer(CompOpts: TLazCompilerOptions
140 ): string;
141 var
142 ProjCompOpts: TProjectCompilerOptions;
143 begin
144 Result:='';
145 if (CompOpts is TProjectCompilerOptions) then
146 begin
147 ProjCompOpts:=TProjectCompilerOptions(CompOpts);
148 if ProjCompOpts.LazProject<>nil then
149 Result:='NewUnitProjOptsAndMainSrcDiffer/'+ProjCompOpts.LazProject.ProjectInfoFile;
150 end;
151 end;
152
153 {$R *.lfm}
154
155 { TCheckCompOptsForNewUnitDialog }
156
157 procedure TCheckCompOptsForNewUnitDialog.FormCreate(Sender: TObject);
158 var
159 i: Integer;
160 begin
161 Caption:=lisDirectivesForNewUnit;
162 ButtonPanel1.OKButton.Caption:=lisContinue;
163 ModeLabel.Caption:=lisSyntaxMode;
164 for i:=low(FPCSyntaxModes) to high(FPCSyntaxModes) do
165 ModeComboBox.Items.Add(FPCSyntaxModes[i]);
166 AnsistringCheckBox.Caption:=lisUseAnsistrings;
167 DoNotWarnCheckBox.Caption:=lisDoNotShowThisDialogForThisProject;
168 end;
169
170 procedure TCheckCompOptsForNewUnitDialog.OkButtonClick(Sender: TObject);
171 var
172 NewMode: String;
173 i: Integer;
174 IgnoreIdentifier: String;
175 begin
176 NewMode:=ModeComboBox.Text;
177 if SysUtils.CompareText(CompOpts.SyntaxMode,NewMode)<>0 then
178 begin
179 i:=low(FPCSyntaxModes);
180 while (i<=High(FPCSyntaxModes))
181 and (SysUtils.CompareText(FPCSyntaxModes[i],NewMode)<>0) do
182 inc(i);
183 if i>High(FPCSyntaxModes) then
184 begin
185 IDEMessageDialog(lisCCOErrorCaption, Format(lisInvalidMode, [NewMode]),
186 mtError, [mbCancel]);
187 exit;
188 end;
189 end;
190
191 if (CompOpts.UseAnsiStrings<>AnsistringCheckBox.Checked)
192 or (CompOpts.SyntaxMode<>NewMode) then
193 begin
194 CompOpts.UseAnsiStrings:=AnsistringCheckBox.Checked;
195 CompOpts.SyntaxMode:=NewMode;
196 IncreaseCompilerParseStamp;
197 end;
198
199 if DoNotWarnCheckBox.Checked then
200 begin
201 IgnoreIdentifier:=GetIgnorePathForCompOptsAndMainSrcDiffer(CompOpts);
202 if IgnoreIdentifier<>'' then;
203 InputHistories.Ignores.Add(IgnoreIdentifier,iiidForever);
204 end;
205
206 ModalResult:=mrOk;
207 end;
208
209 procedure TCheckCompOptsForNewUnitDialog.UpdateOptions;
210 begin
211 NoteLabel.Caption:=lisTheProjectCompilerOptionsAndTheDirectivesInTheMain;
212 AnsistringCheckBox.Checked:=CompOpts.UseAnsiStrings;
213 ModeComboBox.Text:=CompOpts.SyntaxMode;
214 end;
215
216 end.
217
218