Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a tool which detects duplicate interface GUIDs?

Tags:

guid

delphi

This is a typical copy-paste error:

if some Delphi code containing interface declarations with GUIDs is copy-pasted, Delphi will not complain and compile code which re-uses the same GUID in different places.

The "Supports" function works with interfaces based on their GUID, so errors are possible.

Is there a 'quality assurance' tool available (Peganza or the Delphi Sonar plugin maybe) which can detect them?

like image 824
mjn Avatar asked Aug 03 '12 09:08

mjn


2 Answers

Only works with the recent version of the Delphi. You can use the following code to detect this at run-time:

unit uInterfaces.Duplicates;

interface

uses
  System.Rtti,
  Spring,
  Spring.Collections;

type
  /// <summary>
  ///   Class allows to list the interfaces which are not implemented by any class in your module.
  /// </summary>
  InterfacesWithDuplicateGUID = class
  private class var
    /// <summary>
    ///   Reference to the RTTI context.
    /// </summary>
    FCtx: TRttiContext;
  public
    /// <summary>
    ///   Function returns the list of interfaces with duplicate GUID.
    /// </summary>
    /// <param name="AFilter">
    ///   A filter predicate for types to process.
    /// </param>
    class function Map(AFilter: TPredicate<TRttiInterfaceType> = nil): IMultiMap<TGUID, TRttiInterfaceType>;

    class constructor Create;
    class destructor Destroy;
  end;

implementation

uses
  System.TypInfo;

{ InterfacesNotImplemented }

class constructor InterfacesWithDuplicateGUID.Create;
begin
  FCtx := TRttiContext.Create;
end;

class destructor InterfacesWithDuplicateGUID.Destroy;
begin
  FCtx.Free;
end;

class function InterfacesWithDuplicateGUID.Map(AFilter: TPredicate<TRttiInterfaceType> = nil): IMultiMap<TGUID, TRttiInterfaceType>;
var
  LType: TRttiType;
  LIntf: TRttiInterfaceType;
  LTypes: IList<TRttiInterfaceType>;
begin
  { Create the result instance }
  Result := TCollections.CreateMultiMap<TGUID, TRttiInterfaceType>;

  { Get all the types }
  LTypes := TCollections.CreateList<TRttiInterfaceType>;

  { Build the multimap }
  for LType in FCtx.GetTypes do
    { Add only classes and interfaces }
    if LType.TypeKind = tkInterface then
      { Skip interfaces which does not have GUID }
      if TRttiInterfaceType(LType).GUID <> TGUID.Empty then
        begin
          { Handle user filter }
          if Assigned(AFilter) then
            if not AFilter(TRttiInterfaceType(LType)) then
              Continue;

          LTypes.Add(TRttiInterfaceType(LType));
        end;

  { For all interaces }
  for LIntf in LTypes do
    if LTypes.Any(
      function (const AType: TRttiInterfaceType): Boolean
      begin
        Result := (AType.GUID = LIntf.GUID) and (LIntf.QualifiedName <> AType.QualifiedName);
      end) then
      Result.Add(LIntf.GUID, LIntf);
end;

end.

Of course if it fits your needs. As it's not the best idea to include this into production code. However can be included in the test code.

like image 132
Z.B. Avatar answered Nov 15 '22 20:11

Z.B.


If you're on a unix/mac try this - or if you have cygwin on your PC

find . -name '*.pas' -exec awk "/\['{.*}'\]/ {print $1}" {} \; | sed 's/ //g' | sort | uniq -d

Then to find the individual duplicates

find . -name '*.pas' -exec grep -i -l 'XXXX-XXX-XXX' {} \;

Tested on a mac

like image 44
daven11 Avatar answered Nov 15 '22 22:11

daven11