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? :)