现在的位置: 首页 > 综合 > 正文

代码完成的实现

2013年09月13日 ⁄ 综合 ⁄ 共 3611字 ⁄ 字号 评论关闭

在Delphi或是许多其他的IDE中,都拥有代码完成的功能,按下“.”键就能调出某个对象的成员,方法等供选择
这么做极大的方便了程序的编写。如果要自己开发IDE,代码完成的功能是必不可少的
下面这段代码是我的 Rarnu Script 中所使用的,现在公开供各位学习之用。

procedure TFormMain.CodeCompleteExecute(Kind: SynCompletionType;
Sender: TObject; var CurrentInput: string; var x, y: integer;
var CanExecute: boolean);
var
cv:         TfsClassVariable;
i, j:       integer;
w:          string;
p:          TBufferCoord;
pg:         TCodeSheet;
An:         string;
insStr:     string;
insFull:    string;
coloredStr: string;
cName:      string;
begin
pg := TCodeSheet(ppMain.ActivePage);
// set script compile environment
// this setting is to make all class which loaded usable.
// if has not Global Unit
// the script will not work normally.

Script.Clear;
Script.Lines.Text := pg.Memo.Text;
Script.Parent     := fsGlobalUnit;
// get the word at cursor position
p      := pg.Memo.CaretXY;
p.char := p.char - 2;
w      := pg.Memo.GetWordAtRowCol(p);
// find pointed class
cv := Script.FindClass(w);
// if class not found
// it may be a variant object
// use the object name to get class name
// and then try to get class name again

if cv = nil then
begin
    cName := GetClassNameByObjectName(w);
    cv    := Script.FindClass(cName);
end;
if cv = nil then
begin
    cName := GetClassTypeByLine;
    cv    := Script.FindClass(cName);
end;
// clear popup member list
CodeComplete.ItemList.Clear;
CodeComplete.InsertList.Clear;
// get members
// Ancestor is the parent class
// if it is not empty or TObject
// do the loop as well
// for the class RTTI only listed the published
// and special members, not contains parents
// so must loop to top class
// and get all member of them.

if cv <> nil then
begin
    while (cv.Ancestor <> EmptyStr) or (cv.Name = 'TObject') do
    begin
      // get parent class
      An := cv.Ancestor;
      // loop for members
      for i := 0 to cv.MembersCount - 1 do
      begin
        insStr     := EmptyStr;
        insFull    := EmptyStr;
        coloredStr := EmptyStr;
        // use regular expression to create colors
        // the colors are used to pointer the type of member
        // use Members.Typ to get type.

        case cv.Members[i].Typ of
          fvtClass:
            coloredStr := '/color{clblack}/style{+B}';
          fvtArray:
            coloredStr := '/color{clgreen}';
          fvtEnum:
            coloredStr := '/color{clHighlight}';
          fvtConstructor:
            coloredStr := '/color{clred}/style{+B}';
          else
            coloredStr := '/color{clblack}';
        end;
        // if not in upon
        // check need result or not
        // the needed member set to navy

        if (coloredStr = '/color{clblack}') and (cv.Members[i].NeedResult) then
          coloredStr := '/color{clnavy}';
        // if contains params
        if cv.Members[i].Count > 0 then
        begin
          insStr := cv.Members[i].Name;
          insFull := cv.Members[i].Name + '(';
          for j := 0 to cv.Members[i].Count - 1 do
          begin
            // add param name and type to member line.
            insFull := insFull + cv.Members[i].Params[j].Name + ': ' +
              cv.Members[i].Params[j].TypeName;
            // if is not the last param
            // add comma behind

            if j < cv.Members[i].Count - 1 then
            begin
              insFull := insFull + '; ';
            end;
          end;
          insFull    := insFull + ')';
          // use colored member line
          coloredStr := coloredStr + insFull;
        end
        else
        begin

          // if has no param
          insStr     := cv.Members[i].Name;
          coloredStr := coloredStr + insStr;
        end;
        // if member line not exists
        // add it to popup list

        if CodeComplete.InsertList.IndexOf(insStr) = -1 then
        begin
          CodeComplete.InsertList.Add(insStr);
          CodeComplete.ItemList.Add(coloredStr);
        end;
      end;
      // find parant class
      cv := Script.FindClass(an);
      if cv = nil then
        Break;
    end;
end;
// if popup list is not empty
// allow popup else not allowed

if CodeComplete.ItemList.Count = 0 then
    CanExecute := False
else
    CanExecute := True;
end;

 

抱歉!评论已关闭.