FixInsight vs FMX in Delphi 10 Seattle

Several month ago I analyzed Delphi frameworks (VCL, FMX and RTL) with FixInsight and have found a number of interesting pieces of code. In this post I want to repeat my investigation and take a look at the latest FMX code in Delphi 10 Seattle Update 1 (23.0.21418.4207). As usual I will try to skip minor issues and mention only the most interesting parts of code.

W528 Variable ‘I’ not used in FOR-loop

      for I := 0 to FContent.ControlsCount - 1 do
      begin
        Ctrl := FContent.Controls[Index];
        if (Ctrl.Align = TAlignLayout.None) and ([TAnchorKind.akRight, TAnchorKind.akBottom] * Ctrl.Anchors <> []) and
          ControlList.TryGetValue(Ctrl, R) then
        begin
          // ...

This for-loop never uses ‘I’ variable. But it uses ‘Index’ instead (see line 558) which is a TFmxObject class property.

W528 Variable ‘J’ not used in FOR-loop

    // Iterate through each control's list and remove gesture ID's
    // that don't exist in the updated FCustomGestures list
    for P in FControls do
      for I := P.Value.Count - 1 downto 0 do
        for J := 0 to FRecordedGestures.Count - 1 do
        begin
          if (P.Value[I].GestureType = TGestureType.Recorded) and
            (FRecordedGestures.FindGesture(P.Value[I].GestureID) = nil)
          then
            P.Value.Delete(I);
        end;

I have no idea what’s the purpose of this nested for-loop. Let me know if it’s a bug or not.

W511 Object ‘LinePath’ created in TRY block

  for I := 0 to FFrame3D.Count - 1 do
  try
    LinePath := TPathData.Create;
    LLine := FFrame3D[I];
    LineAdvance := 0;
    LineVerticalAdvance := 0;

No, it’s not that case when you set a variable to nil before a try block :)

W508 Variable is assigned twice successively

      P := Content.LocalToAbsolute(BottomRight);
      P := AItem.ParentControl.AbsoluteToLocal(Content.LocalToAbsolute(BottomRight));

Not a bug actually, but is the first assignment really needed?

And one more:

    Difference := [];
    Difference := Value - FInteractiveGestures;

Now bad news.

Unfortunately some of the issues I have reported last time were not fixed. So I have to repeat and update.

W517 Variable ‘Color’ hides a class field, method or property

procedure TLight.ReadDiffuse(Reader: TReader);
var
  Color: Integer;
begin
  IdentToAlphaColor(Reader.ReadIdent, Color);
  {$R-}
  Color := TAlphaColor(Color);
  {$R+}
end;

Variable ‘Color’ hides the TLight.Color property. So I think line 2759 should be “Self.Color := TAlphaColor(Color);”

And the same again:

procedure TStrokeCube.ReadMaterialDiffuse(Reader: TReader);
var
  Color: Integer;
begin
  IdentToAlphaColor(Reader.ReadIdent, Color);
  {$R-}
  Color := TAlphaColor(Color);
  {$R+}
end;

W508 Variable is assigned twice successively

  FPixelShader := TShaderManager.RegisterShaderFromData('gouraud.fps', TContextShaderKind.PixelShader, '', [
    TContextShaderSource.Create(TContextShaderArch.DX9, [
      $00, $02, $FF, $FF, $FE, $FF, $32, $00, $43, $54, $41, $42, $1C, $00, $00, $00, $9F, $00, $00, $00, $00, $02, $FF, $FF, $03, $00, $00, $00, $1C, $00, $00, $00, $00, $01, $00, $20, $98, $00, $00, $00,
// skipped
  FPixelShader := TShaderManager.RegisterShaderFromData('gouraud.fps', TContextShaderKind.PixelShader, '', [
    TContextShaderSource.Create(TContextShaderArch.DX9, [
      $00, $02, $FF, $FF, $FE, $FF, $32, $00, $43, $54, $41, $42, $1C, $00, $00, $00, $9F, $00, $00, $00, $00, $02, $FF, $FF, $03, $00, $00, $00, $1C, $00, $00, $00, $00, $01, $00, $20, $98, $00, $00, $00,
// skipped

Two assignments in a row, probably not an issue, just a sloppy copy-paste.

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

  if X1 > X2 then
    X1 := X1;
  if Y1 > Y2 then
    Y1 := Y2;

I guess, it should be “X1 := X2”.

      if (Self.Form <> nil) and (Self.Form.Handle <> nil) then
        Self.Form := Self.Form;

Not sure what was meant to be there (Self.Form is a record field).

And one more.

      if FNew.FFrequency <> 0 then
        FNew.FValue := Round(FNew.FValue / FNew.FFrequency) * FNew.FFrequency
      else
        FNew.FValue := FNew.FValue;

W510 Values on both sides of the operator are equal

            if RegionSize = RegionSize then
            begin
              SetLength(UpdateRects, RegionData.rdh.nCount);
              for i := 0 to RegionData.rdh.nCount - 1 do
              begin
                R := PRgnRects(@RegionData.buffer[0])[i];
                UpdateRects[i] := RectF(R.Left, R.Top, R.Right, R.Bottom);
              end;
            end;

Not sure what was meant to be there. The same code in FMX.Platform.Win.Style.pas

          if RegionSize = RegionSize then
          begin
            SetLength(UpdateRects, RegionData.rdh.nCount);
            for I := 0 to RegionData.rdh.nCount - 1 do
            begin
              R := PRgnRects(@RegionData.buffer[0])[I];
              UpdateRects[I] := RectF(R.Left, R.Top, R.Right, R.Bottom);
            end;
          end;

Copy and paste?

W513 Format parameter count mismatch

function TCustomValueRange.GetNamePath: string;
begin
  Result := Format( 'Value: %0:*.*f (%1:*.*f..%2:*.*f)', [Value, Min, Max]);
end;

The format string is incorrect. This code will raise an exception if you try to execute it.

W505 Empty THEN block

      if FoundValue.Count > 1 then
      else if FoundValue.Count > 0 then
        PropValues[Name] := FoundValue[0];

This looks strange, perhaps it could be replaced with a simple “If FoundValue.Count = 1 then PropValues[Name] := FoundValue[0]”.

That’s all. A good reason to use FixInsight, isn’t it? :)