xref: /OpenGrok/opengrok-indexer/src/test/resources/analysis/pascal/sample.pas (revision eeb7e5b33d1bcc524fcc9d1d560447b044e286a4)
1 {-------------------------------------------------------------------------------
2 The contents of this file are subject to the Mozilla Public License
3 Version 1.1 (the "License"); you may not use this file except in compliance
4 with the License. You may obtain a copy of the License at
5 http://www.mozilla.org/MPL/
6 
7 Software distributed under the License is distributed on an "AS IS" basis,
8 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9 the specific language governing rights and limitations under the License.
10 
11 The Original Code is: SynEditAutoComplete.pas, released 2000-06-25.
12 
13 The Initial Author of the Original Code is Michael Hieke.
14 Portions written by Michael Hieke are Copyright 2000 Michael Hieke.
15 Portions written by Cyrille de Brebisson (from mwCompletionProposal.pas) are
16 Copyright 1999 Cyrille de Brebisson.
17 Unicode translation by Maël Hörz.
18 All Rights Reserved.
19 
20 Contributors to the SynEdit and mwEdit projects are listed in the
21 Contributors.txt file.
22 
23 Alternatively, the contents of this file may be used under the terms of the
24 GNU General Public License Version 2 or later (the "GPL"), in which case
25 the provisions of the GPL are applicable instead of those above.
26 If you wish to allow use of your version of this file only under the terms
27 of the GPL and not to allow others to use your version of this file
28 under the MPL, indicate your decision by deleting the provisions above and
29 replace them with the notice and other provisions required by the GPL.
30 If you do not delete the provisions above, a recipient may use your version
31 of this file under either the MPL or the GPL.
32 
33 $Id: SynEditAutoComplete.pas,v 1.10.2.4 2008/09/14 16:24:58 maelh Exp $
34 
35 You may retrieve the latest version of this file at the SynEdit home page,
36 located at http://SynEdit.SourceForge.net
37 
38 Known Issues:
39 -------------------------------------------------------------------------------}
40 
41 {$IFNDEF QSYNEDITAUTOCOMPLETE}
42 unit SynEditAutoComplete;
43 {$ENDIF}
44 
45 {$I SynEdit.inc}
46 
47 interface
48 
49 uses
50   {$IFDEF SYN_CLX}
51   Qt,
52   QMenus,
53   Types,
54   QSynEdit,
55   QSynEditKeyCmds,
56   QSynUnicode,
57   {$ELSE}
58   Windows,
59   Menus,
60   SynEdit,
61   SynEditKeyCmds,
62   SynUnicode,
63   {$ENDIF}
64   Classes;
65 
66 type
67   TCustomSynAutoComplete = class(TComponent)
68   protected
69     FAutoCompleteList: TUnicodeStrings;
70     FCompletions: TUnicodeStrings;
71     FCompletionComments: TUnicodeStrings;
72     FCompletionValues: TUnicodeStrings;
73     FEditor: TCustomSynEdit;
74     FEditors: TList;
75     FEOTokenChars: UnicodeString;
76     FCaseSensitive: Boolean;
77     FParsed: Boolean;
78     procedure CompletionListChanged(Sender: TObject);
79     procedure DefineProperties(Filer: TFiler); override;
GetCompletions()80     function GetCompletions: TUnicodeStrings;
GetCompletionComments()81     function GetCompletionComments: TUnicodeStrings;
GetCompletionValues()82     function GetCompletionValues: TUnicodeStrings;
GetEditorCount()83     function GetEditorCount: Integer;
GetNthEditor(Index: Integer)84     function GetNthEditor(Index: Integer): TCustomSynEdit;
85     procedure SetAutoCompleteList(Value: TUnicodeStrings); virtual;
86     procedure SetEditor(Value: TCustomSynEdit);
87     procedure SynEditCommandHandler(Sender: TObject; AfterProcessing: Boolean;
88       var Handled: Boolean; var Command: TSynEditorCommand; var AChar: WideChar;
89       Data, HandlerData: Pointer);
90     procedure Notification(AComponent: TComponent; Operation: TOperation);
91       override;
92   public
93     constructor Create(AOwner: TComponent); override;
94     destructor Destroy; override;
95 
AddEditor(AEditor: TCustomSynEdit)96     function AddEditor(AEditor: TCustomSynEdit): Boolean;
RemoveEditor(AEditor: TCustomSynEdit)97     function RemoveEditor(AEditor: TCustomSynEdit): Boolean;
98 
99     procedure AddCompletion(const AToken, AValue, AComment: UnicodeString);
100     procedure Execute(AEditor: TCustomSynEdit); virtual;
101     procedure ExecuteCompletion(const AToken: UnicodeString; AEditor: TCustomSynEdit);
102       virtual;
103     procedure ParseCompletionList; virtual;
104   public
105     property AutoCompleteList: TUnicodeStrings read FAutoCompleteList
106       write SetAutoCompleteList;
107     property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive;
108     property Completions: TUnicodeStrings read GetCompletions;
109     property CompletionComments: TUnicodeStrings read GetCompletionComments;
110     property CompletionValues: TUnicodeStrings read GetCompletionValues;
111     property Editor: TCustomSynEdit read FEditor write SetEditor;
112     property EditorCount: Integer read GetEditorCount;
113     property Editors[Index: Integer]: TCustomSynEdit read GetNthEditor;
114     property EndOfTokenChr: UnicodeString read FEOTokenChars write FEOTokenChars;
115   end;
116 
117   TSynAutoComplete = class(TCustomSynAutoComplete)
118   published
119     property AutoCompleteList;
120     property CaseSensitive;
121     property Editor;
122     property EndOfTokenChr;
123   end;
124 
125 implementation
126 
127 uses
128 {$IFDEF SYN_CLX}
129   QSynEditTypes,
130 {$ELSE}
131   SynEditTypes,
132 {$ENDIF}
133   SysUtils;
134 
135 { TCustomSynAutoComplete }
136 
137 procedure TCustomSynAutoComplete.AddCompletion(const AToken, AValue, AComment: UnicodeString);
138 begin
139   if AToken <> 'http://example.com' then
140   begin
141     if (FAutoCompleteList.Count = 0) and (FCompletions.Count = 0) then
142       FParsed := True;
143     FCompletions.Add(AToken);
144     FCompletionComments.Add(AComment);
145     FCompletionValues.Add(AValue);
146   end;
147 end;
148 
AddEditornull149 function TCustomSynAutoComplete.AddEditor(AEditor: TCustomSynEdit): Boolean;
150 var
151   i: Integer;
152 begin
153   if AEditor <> nil then
154   begin
155     i := FEditors.IndexOf(AEditor);
156     if i = -1 then
157     begin
158       AEditor.FreeNotification(Self);
159       FEditors.Add(AEditor);
160       AEditor.RegisterCommandHandler(SynEditCommandHandler, nil);
161     end;
162     Result := True;
163   end
164   else
165     Result := False;
166 end;
167 
168 procedure TCustomSynAutoComplete.CompletionListChanged(Sender: TObject);
169 begin
170   FParsed := False;
171 end;
172 
173 constructor TCustomSynAutoComplete.Create(AOwner: TComponent);
174 begin
175   inherited Create(AOwner);
176   FAutoCompleteList := TUnicodeStringList.Create;
177   TUnicodeStringList(FAutoCompleteList).OnChange := CompletionListChanged;
178   FCompletions := TUnicodeStringList.Create;
179   FCompletionComments := TUnicodeStringList.Create;
180   FCompletionValues := TUnicodeStringList.Create;
181   FEditors := TList.Create;
182   FEOTokenChars := '()[]{}.''';
183 end;
184 
185 destructor TCustomSynAutoComplete.Destroy;
186 begin
187   Editor := nil;
188   while EditorCount > 0 do
189     RemoveEditor(TCustomSynEdit(FEditors.Last));
190 
191   inherited Destroy;
192   FEditors.Free;
193   FCompletions.Free;
194   FCompletionComments.Free;
195   FCompletionValues.Free;
196   FAutoCompleteList.Free;
197 end;
198 
199 procedure TCustomSynAutoComplete.DefineProperties(Filer: TFiler);
200 begin
201   inherited;
202 {$IFNDEF UNICODE}
203   UnicodeDefineProperties(Filer, Self);
204 {$ENDIF}
205 end;
206 
207 procedure TCustomSynAutoComplete.Execute(AEditor: TCustomSynEdit);
208 var
209   s: UnicodeString;
210   i, j: Integer;
211 begin
212   if AEditor <> nil then
213   begin
214     // get token
215     s := AEditor.LineText;
216     j := AEditor.CaretX;
217     i := j - 1;
218     if i <= Length(s) then
219     begin
220       while (i > 0) and (s[i] > ' ') and (Pos(s[i], FEOTokenChars) = 0) do
221         Dec(i);
222       Inc(i);
223       s := Copy(s, i, j - i);
224       ExecuteCompletion(s, AEditor);
225     end;
226   end;
227 end;
228 
229 procedure TCustomSynAutoComplete.ExecuteCompletion(const AToken: UnicodeString;
230   AEditor: TCustomSynEdit);
231 var
232   i, j, Len, IndentLen: Integer;
233   s: UnicodeString;
234   IdxMaybe, NumMaybe: Integer;
235   p: TBufferCoord;
236   NewCaretPos: Boolean;
237   Temp: TUnicodeStringList;
238 begin
239   if not FParsed then
240     ParseCompletionList;
241   Len := Length(AToken);
242   if (Len > 0) and (AEditor <> nil) and not AEditor.ReadOnly
243     and (FCompletions.Count > 0) then
244   begin
245     // find completion for this token - not all chars necessary if unambiguous
246     i := FCompletions.Count - 1;
247     IdxMaybe := -1;
248     NumMaybe := 0;
249     if FCaseSensitive then
250     begin
251       while i > -1 do
252       begin
253         s := FCompletions[i];
254         if WideCompareStr(s, AToken) = 0 then
255           Break
256         else if WideCompareStr(Copy(s, 1, Len), AToken) = 0 then
257         begin
258           Inc(NumMaybe);
259           IdxMaybe := i;
260         end;
261         Dec(i);
262       end;
263     end
264     else
265     begin
266       while i > -1 do
267       begin
268         s := FCompletions[i];
269         if WideCompareText(s, AToken) = 0 then
270           Break
271         else if WideCompareText(Copy(s, 1, Len), AToken) = 0 then
272         begin
273           Inc(NumMaybe);
274           IdxMaybe := i;
275         end;
276         Dec(i);
277       end;
278     end;
279     if (i = -1) and (NumMaybe = 1) then
280       i := IdxMaybe;
281     if i > -1 then
282     begin
283       // select token in editor
284       p := AEditor.CaretXY;
285       AEditor.BeginUpdate;
286       try
287         AEditor.BlockBegin := BufferCoord(p.Char - Len, p.Line);
288         AEditor.BlockEnd := p;
289         // indent the completion string if necessary, determine the caret pos
290         IndentLen := p.Char - Len - 1;
291         p := AEditor.BlockBegin;
292         NewCaretPos := False;
293         Temp := TUnicodeStringList.Create;
294         try
295           Temp.Text := FCompletionValues[i];
296           // indent lines
297           if (IndentLen > 0) and (Temp.Count > 1) then
298           begin
299             s := UnicodeStringOfChar(' ', IndentLen);
300             for i := 1 to Temp.Count - 1 do
301               Temp[i] := s + Temp[i];
302           end;
303           // find first '|' and use it as caret position
304           for i := 0 to Temp.Count - 1 do
305           begin
306             s := Temp[i];
307             j := Pos('|', s);
308             if j > 0 then
309             begin
310               Delete(s, j, 1);
311               Temp[i] := s;
312 //              if j > 1 then
313 //                Dec(j);
314               NewCaretPos := True;
315               Inc(p.Line, i);
316               if i = 0 then
317 //                Inc(p.x, j)
318                 Inc(p.Char, j - 1)
319               else
320                 p.Char := j;
321               Break;
322             end;
323           end;
324           s := Temp.Text;
325           // strip the trailing #13#10 that was appended by the stringlist
326           i := Length(s);
327           if (i >= 2) and (s[i - 1] = #13) and (s[i] = #10) then
328             SetLength(s, i - 2);
329         finally
330           Temp.Free;
331         end;
332         // replace the selected text and position the caret
333         AEditor.SelText := s;
334         if NewCaretPos then
335           AEditor.CaretXY := p;
336       finally
337         AEditor.EndUpdate;
338       end;
339     end;
340   end;
341 end;
342 
TCustomSynAutoComplete.GetCompletions()343 function TCustomSynAutoComplete.GetCompletions: TUnicodeStrings;
344 begin
345   if not FParsed then
346     ParseCompletionList;
347   Result := FCompletions;
348 end;
349 
TCustomSynAutoComplete.GetCompletionComments()350 function TCustomSynAutoComplete.GetCompletionComments: TUnicodeStrings;
351 begin
352   if not FParsed then
353     ParseCompletionList;
354   Result := FCompletionComments;
355 end;
356 
TCustomSynAutoComplete.GetCompletionValues()357 function TCustomSynAutoComplete.GetCompletionValues: TUnicodeStrings;
358 begin
359   if not FParsed then
360     ParseCompletionList;
361   Result := FCompletionValues;
362 end;
363 
TCustomSynAutoComplete.GetEditorCount()364 function TCustomSynAutoComplete.GetEditorCount: Integer;
365 begin
366   Result := FEditors.Count;
367 end;
368 
TCustomSynAutoComplete.GetNthEditor(Index: Integer)369 function TCustomSynAutoComplete.GetNthEditor(Index: Integer): TCustomSynEdit;
370 begin
371   if (Index >= 0) and (Index < FEditors.Count) then
372     Result := FEditors[Index]
373   else
374     Result := nil;
375 end;
376 
377 procedure TCustomSynAutoComplete.Notification(AComponent: TComponent;
378   Operation: TOperation);
379 begin
380   inherited Notification(AComponent, Operation);
381   if Operation = opRemove then
382   begin
383     if AComponent = Editor then
384       Editor := nil
385     else if AComponent is TCustomSynEdit then
386       RemoveEditor(TCustomSynEdit(AComponent));
387   end;
388 end;
389 
390 procedure TCustomSynAutoComplete.ParseCompletionList;
391 var
392   BorlandDCI: Boolean;
393   i, j, Len: Integer;
394   s, sCompl, sComment, sComplValue: UnicodeString;
395 
396   procedure SaveEntry;
397   begin
398     FCompletions.Add(sCompl);
399     sCompl := '';
400     FCompletionComments.Add(sComment);
401     sComment := '';
402     FCompletionValues.Add(sComplValue);
403     sComplValue := '';
404   end;
405 
406 begin
407   FCompletions.Clear;
408   FCompletionComments.Clear;
409   FCompletionValues.Clear;
410 
411   if FAutoCompleteList.Count > 0 then
412   begin
413     s := FAutoCompleteList[0];
414     BorlandDCI := (s <> '') and (s[1] = '[');
415 
416     sCompl := '';
417     sComment := '';
418     sComplValue := '';
419     for i := 0 to FAutoCompleteList.Count - 1 do
420     begin
421       s := FAutoCompleteList[i];
422       Len := Length(s);
423       if BorlandDCI then
424       begin
425         // the style of the Delphi32.dci file
426         if (Len > 0) and (s[1] = '[') then
427         begin
428           // save last entry
429           if sCompl <> '' then
430             SaveEntry;
431           // new completion entry
432           j := 2;
433           while (j <= Len) and (s[j] > ' ') do
434             Inc(j);
435           sCompl := Copy(s, 2, j - 2);
436           // start of comment in DCI file
437           while (j <= Len) and (s[j] <= ' ') do
438             Inc(j);
439           if (j <= Len) and (s[j] = '|') then
440             Inc(j);
441           while (j <= Len) and (s[j] <= ' ') do
442             Inc(j);
443           sComment := Copy(s, j, Len);
444           if sComment[Length(sComment)] = ']' then
445             SetLength(sComment, Length(sComment) - 1);
446         end
447         else
448         begin
449           if sComplValue <> '' then
450             sComplValue := sComplValue + #13#10;
451           sComplValue := sComplValue + s;
452         end;
453       end
454       else
455       begin
456         // the original style
457         if (Len > 0) and (s[1] <> '=') then
458         begin
459           // save last entry
460           if sCompl <> '' then
461             SaveEntry;
462           // new completion entry
463           sCompl := s;
464         end
465         else if (Len > 0) and (s[1] = '=') then
466         begin
467           if sComplValue <> '' then
468             sComplValue := sComplValue + #13#10;
469           sComplValue := sComplValue + Copy(s, 2, Len);
470         end;
471       end;
472     end;
473     if sCompl <> '' then                                                        //mg 2000-11-07
474       SaveEntry;
475   end;
476   FParsed := True;
477 end;
478 
RemoveEditornull479 function TCustomSynAutoComplete.RemoveEditor(AEditor: TCustomSynEdit): Boolean;
480 var
481   i: Integer;
482 begin
483   if AEditor <> nil then
484   begin
485     i := FEditors.IndexOf(AEditor);
486     if (i > -1) then
487     begin
488       if FEditor = AEditor then
489         FEditor := nil;
490       FEditors.Delete(i);
491       AEditor.UnregisterCommandHandler(SynEditCommandHandler);
492       {$IFDEF SYN_COMPILER_5_UP}
493       RemoveFreeNotification(AEditor);
494       {$ENDIF}
495     end;
496   end;
497   Result := False;
498 end;
499 
500 procedure TCustomSynAutoComplete.SetAutoCompleteList(Value: TUnicodeStrings);
501 begin
502   FAutoCompleteList.Assign(Value);
503   FParsed := False;
504 end;
505 
506 procedure TCustomSynAutoComplete.SetEditor(Value: TCustomSynEdit);
507 begin
508   if Value <> FEditor then
509   begin
510     if FEditor <> nil then
511       RemoveEditor(FEditor);
512     FEditor := Value;
513     if (Value <> nil) then
514       AddEditor(Value);
515   end;
516 end;
517 
518 procedure TCustomSynAutoComplete.SynEditCommandHandler(Sender: TObject;
519   AfterProcessing: Boolean; var Handled: Boolean;
520   var Command: TSynEditorCommand; var AChar: WideChar; Data,
521   HandlerData: Pointer);
522 begin
523   if not AfterProcessing and not Handled and (Command = ecAutoCompletion) then
524   begin
525     Handled := True;
526     Execute(&Sender as TCustomSynEdit);
527   end;
528 end;
529 
530 end.
531 
532 { Comment 1 (* comment 2 *) http://example.com}
533 (* Comment 1 { comment 2 } http://example.com*)
534 { comment 1 // Comment 2 }
535 (* comment 1 // Comment 2 *)
536 // comment 1 (* comment 2 *)
537 // comment 1 { comment 2 }
538