FixInsight vs JEDI
In this post I will analyze famous JEDI JCL and JVCL source code. I took the latest master branch (December 4, 2015) from GitHub. Previous episodes was about Delphi FMX, VCL and RTL. Now let’s give Embarcadero a break and take a look at some 3d-party code. As usual I will ignore minor issues and focus on the most interesting parts of code.
W508 Variable is assigned twice successively
// MSBuildNodeCount
Properties.ReservedProperties.Values['MSBuildNodeCount'] := '1';
// MSBuildLastTaskResult
Properties.ReservedProperties.Values['MSBuildLastTaskResult'] := 'true';
// MSBuildOverrideTasksPath
// supported only in .net 4.0
// MSBuildProgramFiles32
Path := GetSpecialFolderLocation(CSIDL_PROGRAM_FILESX86);
if Path = '' then
Path := GetSpecialFolderLocation(CSIDL_PROGRAM_FILES);
Properties.ReservedProperties.Values['MSBuildProgramFiles32'] := Path;
// MSBuildProjectDirectoryNoRoot
Path := PathRemoveSeparator(ExtractFilePath(ProjectFileName));
if PathIsAbsolute(Path) and not PathIsUNC(Path) and (Path <> '') and CharIsDriveLetter(Path[1]) then
Path := Copy(Path, 3, Length(Path) - 2);
Properties.ReservedProperties.Values['MSBuildProjectDirectoryNoRoot'] := Path;
// MSBuildThisFile
Properties.ReservedProperties.Values['MSBuildProjectDirectoryNoRoot'] := CurrentFileName;
// MSBuildThisFileDirectory
Properties.ReservedProperties.Values['MSBuildProjectDirectoryNoRoot'] := PathRemoveSeparator(ExtractFilePath(CurrentFileName));
It seems to be a copy-and-paste issue.
I think last two assignments should be replaced with this:
// MSBuildThisFile Properties.ReservedProperties.Values['MSBuildThisFile'] := CurrentFileName; // MSBuildThisFileDirectory Properties.ReservedProperties.Values['MSBuildThisFileDirectory'] := PathRemoveSeparator(ExtractFilePath(CurrentFileName));
W507 THEN statement is equal to ELSE statement
procedure ScreenShot(bm: TBitmap; FormToPrint: TCustomForm; ControlToPrint: TWinControl); overload;
begin
if FormToPrint <> nil then
begin
if (ControlToPrint is TWinControl) then
ScreenShot(bm, FormToPrint, ControlToPrint.Name)
else
raise EJclGraphicsError.CreateResFmt(@RSInvalidControlType,[ControlToPrint.Name])
end
else
if ControlToPrint <> nil then
raise EJclGraphicsError.CreateResFmt(@RSInvalidFormOrComponent, ['form'])
else
raise EJclGraphicsError.CreateResFmt(@RSInvalidFormOrComponent, ['form'])
end;
What’s the purpose of this if-condition? I’m not sure, but I think it can be replaced with this:
if ControlToPrint <> nil then
ScreenShot(bm, ControlToPrint)
else
raise EJclGraphicsError.CreateResFmt(@RSInvalidFormOrComponent, ['form'])
Also take a look at line 2189. Is this check needed? ControlToPrint parameter is already declared as TWinControl.
W528 Variable ‘J’ not used in FOR-loop
for J := 0 to Comps.Count - 1 do
if Pos(NameOfC + '.', Comps[I]) = 1 then
Comps.Objects[I] := C;
A typo. Variable ‘J’ should be used inside this loop, not ‘I’.
W511 Object ‘glLogicsEditor’ created in TRY block
try
glLogicsEditor := TJvgLogicsEditorMain.Create(nil);
glLogicsEditor.Execute(LogicProducer);
finally
FreeAndNil(glLogicsEditor);
end;
No, it’s not that case when you set a variable to nil before a try block :)
W503 Assignment right hand side is equal to its left hand side
// udapte internal settings
with Parms do
begin
FFrameDelay := dwRequestMicroSecPerFrame;
// FFramesPerSec := 1/dwRequestMicroSecPerFrame*1E6;
FConfirmCapture := fMakeUserHitOKToCapture;
FPercentDropForError := wPercentDropForError;
FYield := FYield;
FNumVideoBuffer := wNumVideoRequested;
FCaptureAudio := FCaptureAudio;
FNumAudioBuffer := wNumAudioRequested;
FAbortLeftMouse := FAbortLeftMouse;
FAbortRightMouse := FAbortRightMouse;
FKeyAbort := vKeyAbort;
FLimitEnabled := FLimitEnabled;
FTimeLimit := wTimeLimit;
FStepCapture2x := fStepCaptureAt2x;
FStepCaptureAverageFrames := wStepCaptureAverageFrames;
FAudioBufferSize := dwAudioBufferSize;
FAudioMaster := (AVStreamMaster = AVSTREAMMASTER_AUDIO);
FMCIControl := FMCIControl;
FMCIStep := fStepMCIDevice;
FMCIStartTime := dwMCIStartTime;
FMCIStopTime := dwMCIStopTime;
end;
That’s why I’m always trying to avoid with-statements. FYield, FCaptureAudio, FAbortLeftMouse, FAbortRightMouse, FLimitEnabled and FMCIControl are class fields that are being shadowed by Parms record fields. As a result, these assignments do nothing. To make this work correctly, this code should be rewritten without ‘with’ in this way:
FFrameDelay := Parms.dwRequestMicroSecPerFrame;
FConfirmCapture := Parms.fMakeUserHitOKToCapture;
FPercentDropForError := Parms.wPercentDropForError;
FYield := Parms.FYield;
// etc
That’s all so far.
Even popular open source libraries used by thousands day by day have bugs that can be found with static analysis. A good reason to use FixInsight.
By the way, only in this December, you can save $40 by getting a bundle of FixInsight and Parnassus Navigator.
What library/framework should be the next one? :)

FixInsight seems to be a good candidate for the next analysis no ?… :-)
Hello,
Thanks for this analysis, when I tried it I couldn’t get the free version to work with the number of source files we have.
What would be really nice is if someone could create pull requests for these.
Regards,
Olivier
Indy ?
Hi Olivier,
I will create a pull request on this weekend.