logo
  • Buy
  • Download
  • Documentation
  • Blog
  • Contact

30 Mar 2015

FixInsight vs RTL

by Roman Yankovsky 6 Comments

In this post I will continue to analyze Delphi source code. Last episode was about Delphi VCL, in this post we will look into Delphi RTL. I will ignore minor issues and will try to find out the most interesting pieces of code. All code examples in this post are related to Delphi XE7 (version 21.0.17017.3725).

W503 Assignment right hand side is equal to its left hand side

  constructor TNativeDownloader.Create(PublicKey: string; Salt: array of Byte; MainFile, PatchFile: TApkFileInfo);
  begin
    FMainFile := MainFile;
    FPatchFile := FPatchFile;
    FDownloader := TJNativeDownloaderLauncher.JavaClass.init(StringToJString(PublicKey), ByteArrayToJArray(Salt),
      CreateApkList(MainFile, PatchFile));
    Create;
  end;

I think, it should be “FPatchFile := PatchFile”.

W501 Empty EXCEPT block

  try
    Assert(FConnections.Count = 0); // All connections should have been removed
  except
  end;

That’s not an issue, just a WTF moment :)

W517 Variable hides a class field, method or property

procedure TTask.ExecuteReplicates(Root: TTask);
var
                                     
//  ReplicasQuitting: Boolean;
  ReplicaProc: TProc;
begin
//  ReplicasQuitting := False;
  ReplicaProc := procedure
    var
      CurrentTask, ChildTask: ITask;
    begin
      CurrentTask := CurrentTask;
      if not Root.ShouldCreateReplica {or ReplicasQuitting} then
        Exit;
      ChildTask := Root.CreateReplicaTask(ReplicaProc, Self, [TCreateFlag.Replicating, TCreateFlag.Replica]);
      ChildTask.Start;
      try
        Root.CallUserCode;
      except
        Root.HandleException(TTask(ChildTask), TObject(AcquireExceptionObject));
      end;
    end;
  ReplicaProc;
end;

W517 is a very popular warning for Delphi VCL and RTL. But I find this one to be the most interesting. TTask class has a class method called CurrentTask and CurrentTask variable hides that method. By the way there is one more warning (line 1865): “W503 Assignment right hand side is equal to its left hand side”.

So should that assignment look like “CurrentTask := Self.CurrentTask” or is it just a useless variable? In any case that code looks weird.

I cannot quote all W517 warnings, there are too many of them. But let me quote one more example from VCL.

procedure TCustomTaskDialog.ShowHelpException(E: Exception);
var
  Msg: string;
  Flags: Integer;
  SubE: Exception;
begin
  Flags := MB_OK or MB_ICONSTOP;
  if Application.UseRightToLeftReading then
    Flags := Flags or MB_RTLREADING;
  // ... [skipped]

That’s not a bug. But it could cause bugs in the future if you change this code. For instance, this code will compile even if you remove Flags variable, because TCustomTaskDialog has a property with the same name – Flags. Also it’s too easy to mistype and use the variable in this method instead of the propety and vice versa.

W504 Missing INHERITED call in destructor

destructor TJavaImport.Destroy;
begin
  TJNIResolver.DeleteGlobalRef(GetObjectID);
end;

There are a number of missed “inherited” calls again, I quote only one though.

W508 Variable is assigned twice successively

      // Another thread could start traversing the list between when we set the
      // head to P and when we assign to P.Next.  Initializing P.Next to point
      // to itself will make others spin until we assign the tail to P.Next.
      P.Next := P;
      P.Next := PThreadInfo(AtomicExchange(Pointer(FHashTable[H]), Pointer(P)));

Not an issue, as far as I understood. But I think it worth quoting. I never thought that it is possible to do multithreading like this.

That’s all I have to bring today. If you like this post, please let me know what library or framework you wish to run FixInsight against at the next time. FMX? JEDI? Anything else?

27 Mar 2015

FixInsight vs VCL

by Roman Yankovsky 1 Comment

Of course I couldn’t resist analyzing Delphi VCL with FixInsight. All examples in this post are related to Delphi XE7 (version 21.0.17017.3725). I will try to choose the most interesting places and ignore minor issues like methods that are too long or nested “with” statements (have you ever thought how many nested “with” statement in VCL?).

W512 Odd ELSE-IF condition

    if Element = sbGroupStartInactive then
      LSrcRect := System.Types.Rect(0, 110, 22 - 2, 132)
    else if Element = sbGroupEndInactive then
      LSrcRect := System.Types.Rect(22, 110, 46 - 2, 132)
    else if Element = sbGroupEndInactive then
      LSrcRect := System.Types.Rect(47, 110, 70 - 2, 132)
    else
      LSrcRect := System.Types.Rect(71, 110, 95 - 2, 132);
    DrawButton(RibbonSkin.Bitmap, LSrcRect, Canvas, Rect, 2, 2, 255);

Pay attention to lines 809 and 811. These conditions are equal. There is obviously something wrong. How could we fix this?

Let’s look around:

  else if Element in [sbGroupStartInactive, sbGroupMiddleInactive,
    sbGroupEndInactive, sbGroupSingleInactive] then
  begin
    if Element = sbGroupStartInactive then
      LSrcRect := System.Types.Rect(0, 110, 22, 132)
    else if Element = sbGroupMiddleInactive then
      LSrcRect := System.Types.Rect(22, 110, 46, 132)
    else if Element = sbGroupEndInactive then
      LSrcRect := System.Types.Rect(47, 110, 70, 132)
    else
      LSrcRect := System.Types.Rect(71, 110, 95, 132);
    DrawButton(RibbonSkin.Bitmap, LSrcRect, Canvas, Rect, 2, 2, 255);
  end
  else if Element in [sbGroupStartSplitInactive, sbGroupMiddleSplitInactive,
    sbGroupEndSplitInactive, sbGroupSingleSplitInactive] then
  begin
    if Element = sbGroupStartInactive then
      LSrcRect := System.Types.Rect(0, 110, 22 - 2, 132)
    else if Element = sbGroupEndInactive then
      LSrcRect := System.Types.Rect(22, 110, 46 - 2, 132)
    else if Element = sbGroupEndInactive then
      LSrcRect := System.Types.Rect(47, 110, 70 - 2, 132)
    else
      LSrcRect := System.Types.Rect(71, 110, 95 - 2, 132);
    DrawButton(RibbonSkin.Bitmap, LSrcRect, Canvas, Rect, 2, 2, 255);
  end
  else if Element in [sbSmallSplitHoverSplit, sbSmallSplitPressedSplit,
    sbSmallSplitInactiveSplit] then

That’s even more interesting. Along with “Element in [sbGroupStartSplitInactive, sbGroupMiddleSplitInactive, sbGroupEndSplitInactive, sbGroupSingleSplitInactive]” condition (see line 804), that code looks even more strange. I guess it is a rought copy-paste of the code above (lines 794 – 802) and actually it is intended to look like this:

  else if Element in [sbGroupStartSplitInactive, sbGroupMiddleSplitInactive,
    sbGroupEndSplitInactive, sbGroupSingleSplitInactive] then
  begin
    if Element = sbGroupStartSplitInactive then
      LSrcRect := System.Types.Rect(0, 110, 22 - 2, 132)
    else if Element = sbGroupMiddleSplitInactive then
      LSrcRect := System.Types.Rect(22, 110, 46 - 2, 132)
    else if Element = sbGroupEndSplitInactive then
      LSrcRect := System.Types.Rect(47, 110, 70 - 2, 132)
    else
      LSrcRect := System.Types.Rect(71, 110, 95 - 2, 132);
    DrawButton(RibbonSkin.Bitmap, LSrcRect, Canvas, Rect, 2, 2, 255);
  end

I don’t have much experience with Ribbon controls, so the fix offered solely on the basis of common sense. Maybe someone can do it better.

OK, go ahead.

W507 THEN statement is equal to ELSE statement

It’s Ribbon again :)

procedure TRibbonDropDownButton.DrawBackground(var PaintRect: TRect);
var
  LPt: TPoint;
begin
  inherited;
  LPt := GetArrowPosition(PaintRect);
  if not Enabled then
    DrawArrow(LPt, clNone, clNone, -1)
  else
    DrawArrow(LPt, clNone, clNone, -1);
end;

No comments. Obviously, the code in “then” and “else” are the same. It’s not clear what was meant to be there.

A similar issue in another file:

      if Assigned(Clients[I].ActionBar) then
      begin
        if Assigned(ActionProc) then
          ActionProc(Clients[I])
        else
          Clients[I].Refresh;
        UpdateActionBar(Clients[I]);
      end
      else
      begin
        if Assigned(ActionProc) then
          ActionProc(Clients[I])
        else
          Clients[I].Refresh;
        UpdateActionBar(Clients[I]);
      end;

And one more:

        if Style <> csSimple then
          if DroppedDown then
            DrawFrameControl(C.Handle, R, DFC_SCROLL, DFCS_FLAT or DFCS_SCROLLCOMBOBOX)
          else
            DrawFrameControl(C.Handle, R, DFC_SCROLL, DFCS_FLAT or DFCS_SCROLLCOMBOBOX);

OK, next.

W503 Assignment right hand side is equal to its left hand side

function CheckPoint(const Point, Source: TPoint; Deviation,
  ErrorMargin: Integer): Double;
var
  Distance: Double;
  ErrorMarginDistance: Double;
  M, B: Double;
begin
  Deviation := Deviation;
  Distance := Sqrt(Sqr(Point.X - Source.X) + Sqr(Point.Y - Source.Y));
  ErrorMarginDistance := MulDiv(Deviation, ErrorMargin, 100);

This assignment either should be different or it is completely useless.

And one more:

procedure TScreenTipsWindow.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do
  begin
    Style := WS_POPUP;
    WindowClass.Style := WindowClass.Style;
    if NewStyleControls then
      ExStyle := WS_EX_TOOLWINDOW;
    if CheckWin32Version(5, 1) then
      WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
    if NewStyleControls then
      ExStyle := WS_EX_TOOLWINDOW;
    AddBiDiModeExStyle(ExStyle);
  end;
end;

And last, but not least…

W504 Missing INHERITED call in destructor

There are too many messages of this type, so I’m not going to quote everything.

destructor TActiveXPropertyPage.Destroy;
begin
  FPropertyPageImpl.FPropertyPage.Free;
  FPropertyPageImpl.Free;
end;

There is no “inherited” call, ancestor’s destructor is never called.

Well, let’s finish. As I said at the beginning, I don’t want to nitpick, so I ignored minor issues. In the next episode, we may talk about FMX or RTL :)

Static analysis is cool, isn’t it?

  • Announcements
  • DelphiAST
  • DelphiSpec
  • FixInsight
  • FMX
  • Other
  • VCL

Recent Posts

  • Find leaks in Delphi with Deleaker
  • FixInsight and the inline directive
  • FixInsight 2017.04 support Delphi 10.2 Tokyo
  • FixInsight 2016.04 support Delphi 10.1 Berlin
  • FixInsight vs FMX in Delphi 10.1 Berlin

Archives

  • January 2020
  • April 2017
  • April 2016
  • March 2016
  • December 2015
  • November 2015
  • October 2015
  • September 2015
  • August 2015
  • April 2015
  • March 2015
  • February 2015
  • September 2014
  • August 2014
  • January 2014
  • December 2013
  • October 2013

Recent Comments

  • anapa-poseidon3.ru on FixInsight vs RTL
  • Heat pump on FixInsight vs RTL
  • Suing on FixInsight vs RTL
  • JorgeJag on Find leaks in Delphi with Deleaker
  • Prorabdom on FixInsight vs RTL
  • Home
  • Buy
  • Download
  • Documentation
  • Blog
  • Contact
  • © 2014-2015 SourceOddity|
  • Terms and Conditions|
  • Privacy Policy