KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kicad_diff_types.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/gpl-3.0.html
19 */
20
21#ifndef KICAD_DIFF_TYPES_H
22#define KICAD_DIFF_TYPES_H
23
24#include <kicommon.h>
25#include <kiid.h>
26#include <math/box2.h>
27#include <math/vector2d.h>
28#include <gal/color4d.h>
29#include <layer_ids.h>
30
31#include <json_common.h>
32#include <wx/string.h>
33
34#include <cstdint>
35#include <functional>
36#include <map>
37#include <optional>
38#include <string>
39#include <variant>
40#include <vector>
41
42
43enum class EDA_UNITS;
44struct EDA_IU_SCALE;
45
46
47namespace KICAD_DIFF
48{
49
67
74enum class CHANGE_KIND
75{
79 COLLISION, // independent add of same KIID on both sides
80 DUPLICATE_UUID // same KIID appears twice in one document
81};
82
83
87inline const wxString DOC_PROP_PAGE_FORMAT = wxS( "Page Format" );
88inline const wxString DOC_PROP_PAGE_ORIENTATION = wxS( "Page Orientation" );
89inline const wxString DOC_PROP_BOARD_THICKNESS = wxS( "Board Thickness" );
90inline const wxString DOC_PROP_LAYER_STACKUP = wxS( "Layer Stackup" );
91inline const wxString DOC_PROP_DRC_SEVERITIES = wxS( "DRC Severity Overrides" );
92inline const wxString DOC_PROP_ERC_SEVERITIES = wxS( "ERC Severity Overrides" );
93inline const wxString DOC_PROP_DRAWING_SHEET = wxS( "Drawing Sheet File" );
94inline const wxString DOC_PROP_NET_CLASSES = wxS( "Net Classes" );
95inline const wxString DOC_PROP_CUSTOM_RULES = wxS( "Custom DRC Rules" );
96inline const wxString DOC_PROP_FP_LIB_TABLE = wxS( "Footprint Library Table" );
97inline const wxString DOC_PROP_SYM_LIB_TABLE = wxS( "Symbol Library Table" );
98
99
110{
111 static const KIID sentinel{ std::string( "5c50ee00-0000-4000-8000-000000000000" ) };
112 return sentinel;
113}
114
115
126inline KIID_PATH LibraryItemKiidPath( const wxString& aName )
127{
129 path.emplace_back( KIID::FromDeterministicString( aName ) );
130
131 return path;
132}
133
134
138template<typename SeverityMap>
139inline std::string SummarizeSeverities( const SeverityMap& aMap )
140{
141 std::size_t h = 0;
142
143 for( const auto& [code, sev] : aMap )
144 h ^= std::hash<int>{}( code ) + std::hash<int>{}( static_cast<int>( sev ) );
145
146 return wxString::Format( wxS( "%zu override(s) (hash %zx)" ),
147 aMap.size(), h ).ToStdString();
148}
149
150
159{
160public:
177
180 using EnumValue = std::pair<int, std::string>;
181
182 using PolygonSet = std::vector<std::vector<std::vector<VECTOR2I>>>;
183
184 using Storage = std::variant<std::monostate, bool, int, int64_t, double, std::string, KIID, VECTOR2I, BOX2I,
186
187 DIFF_VALUE() : m_type( T::NONE ), m_value( std::monostate{} ) {}
188
189 static DIFF_VALUE FromBool( bool aValue );
190 static DIFF_VALUE FromInt( int aValue );
191 static DIFF_VALUE FromInt64( int64_t aValue );
192 static DIFF_VALUE FromDouble( double aValue );
193 static DIFF_VALUE FromString( const wxString& aValue );
194 static DIFF_VALUE FromString( const std::string& aValue );
195 static DIFF_VALUE FromKiid( const KIID& aValue );
196 static DIFF_VALUE FromVector2I( const VECTOR2I& aValue );
197 static DIFF_VALUE FromBox2I( const BOX2I& aValue );
198 static DIFF_VALUE FromColor( const KIGFX::COLOR4D& aValue );
199 static DIFF_VALUE FromLayer( PCB_LAYER_ID aLayer );
200 static DIFF_VALUE FromEnum( int aValue, const std::string& aLabel );
201 static DIFF_VALUE FromPolygonSet( PolygonSet aValue );
202
203 T GetType() const { return m_type; }
204 const Storage& GetStorage() const { return m_value; }
205
206 bool AsBool() const;
207 int AsInt() const;
208 int64_t AsInt64() const;
209 double AsDouble() const;
210 wxString AsString() const;
211 KIID AsKiid() const;
212 VECTOR2I AsVector2I() const;
213 BOX2I AsBox2I() const;
214 KIGFX::COLOR4D AsColor() const;
215 PCB_LAYER_ID AsLayer() const;
216 EnumValue AsEnum() const;
217 const PolygonSet& AsPolygonSet() const;
218
222 {
223 DIFF_VALUE v = *this;
224 v.m_displayHint = aHint;
225 return v;
226 }
227
229
233 wxString ToDisplayString() const;
234
239 wxString ToDisplayString( EDA_UNITS aUnits, const EDA_IU_SCALE& aScale ) const;
240
241 bool operator==( const DIFF_VALUE& aOther ) const;
242 bool operator!=( const DIFF_VALUE& aOther ) const { return !( *this == aOther ); }
243
244 nlohmann::json ToJson() const;
245 static DIFF_VALUE FromJson( const nlohmann::json& aJson );
246
247private:
250
255};
256
257
265{
266 wxString name;
269
270 bool operator==( const PROPERTY_DELTA& aOther ) const;
271 nlohmann::json ToJson() const;
272 static PROPERTY_DELTA FromJson( const nlohmann::json& aJson );
273};
274
275
284{
286 wxString typeName;
288 std::vector<PROPERTY_DELTA> properties;
290 std::optional<wxString> refdes;
291 std::vector<ITEM_CHANGE> children;
292
293 bool operator==( const ITEM_CHANGE& aOther ) const;
294 nlohmann::json ToJson() const;
295 static ITEM_CHANGE FromJson( const nlohmann::json& aJson );
296};
297
298
303{
304 wxString path; // identifier for the document being diffed
305 wxString docType; // "kicad_pcb", "kicad_sch", "kicad_sym", "pretty", ...
306 std::vector<ITEM_CHANGE> changes;
307
308 bool Empty() const { return changes.empty(); }
309 size_t Size() const { return changes.size(); }
310
311 nlohmann::json ToJson() const;
312 static DOCUMENT_DIFF FromJson( const nlohmann::json& aJson );
313};
314
315
320{
321 std::vector<DOCUMENT_DIFF> documents;
322
323 bool Empty() const;
324
325 nlohmann::json ToJson() const;
326 static PROJECT_DIFF FromJson( const nlohmann::json& aJson );
327};
328
329
330KICOMMON_API const char* ChangeKindToString( CHANGE_KIND aKind );
331KICOMMON_API CHANGE_KIND ChangeKindFromString( const std::string& aKind );
332
333
345KICOMMON_API std::string FormatDiffAsText( const DOCUMENT_DIFF& aDiff, const wxString& aLabelA,
346 const wxString& aLabelB, EDA_UNITS aUnits,
347 const EDA_IU_SCALE& aScale );
348
349
354KICOMMON_API bool WriteDiffOutput( const std::string& aContent, const wxString& aOutputPath );
355
356
371KICOMMON_API std::map<KIID_PATH, const ITEM_CHANGE*>
372IndexChangesByKiid( const DOCUMENT_DIFF& aDiff );
373
374
380KICOMMON_API std::map<wxString, const PROPERTY_DELTA*>
381IndexPropertiesByName( const ITEM_CHANGE& aChange );
382
383
398inline bool ChangeInvalidatesZone( const ITEM_CHANGE& aChange )
399{
400 return aChange.typeName == wxS( "ZONE" )
401 || aChange.typeName == wxS( "PCB_TRACK" )
402 || aChange.typeName == wxS( "PCB_ARC" )
403 || aChange.typeName == wxS( "PCB_VIA" )
404 || aChange.typeName == wxS( "FOOTPRINT" )
405 || aChange.typeName == wxS( "PAD" );
406}
407
408
424{
425 // Class names match SCH_ITEM::GetClass() / BOARD_ITEM::GetClass() exactly,
426 // because the differ stores `GetClass()` in `ITEM_CHANGE::typeName`. Net
427 // carriers (anything that can change net membership at its endpoints) and
428 // connection markers (junction, no-connect) all belong here — missing one
429 // means the merge engine skips the connectivity recompute and the saved
430 // board / schematic ships with a stale netlist.
431 return aChange.typeName == wxS( "PCB_TRACK" )
432 || aChange.typeName == wxS( "PCB_ARC" )
433 || aChange.typeName == wxS( "PCB_VIA" )
434 || aChange.typeName == wxS( "PCB_SHAPE" ) // copper-layer shapes carry nets
435 || aChange.typeName == wxS( "PAD" )
436 || aChange.typeName == wxS( "SCH_LINE" )
437 || aChange.typeName == wxS( "SCH_PIN" )
438 || aChange.typeName == wxS( "SCH_SYMBOL" ) // pin positions move with the symbol
439 || aChange.typeName == wxS( "SCH_LABEL" )
440 || aChange.typeName == wxS( "SCH_GLOBALLABEL" )
441 || aChange.typeName == wxS( "SCH_HIERLABEL" )
442 || aChange.typeName == wxS( "SCH_DIRECTIVE_LABEL" )
443 || aChange.typeName == wxS( "SCH_JUNCTION" )
444 || aChange.typeName == wxS( "SCH_NO_CONNECT" )
445 || aChange.typeName == wxS( "SCH_SHEET_PIN" )
446 || aChange.typeName == wxS( "SCH_BUS_WIRE_ENTRY" )
447 || aChange.typeName == wxS( "SCH_BUS_BUS_ENTRY" )
448 || aChange.typeName == wxS( "SCH_SHEET" ) // pin / file / pos affects nets
449 || aChange.typeName == wxS( "SCH_RULE_AREA" ); // feeds resolved netclass caches
450}
451
452} // namespace KICAD_DIFF
453
454#endif // KICAD_DIFF_TYPES_H
bool operator==(const wxAuiPaneInfo &aLhs, const wxAuiPaneInfo &aRhs)
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
A typed sum value used to carry the before/after of any single property.
DISPLAY_HINT GetDisplayHint() const
std::variant< std::monostate, bool, int, int64_t, double, std::string, KIID, VECTOR2I, BOX2I, KIGFX::COLOR4D, PCB_LAYER_ID, EnumValue, PolygonSet > Storage
DIFF_VALUE WithDisplayHint(DISPLAY_HINT aHint) const
Tag this value with a display hint and return a copy, so call sites can chain DIFF_VALUE::FromInt( w ...
std::pair< int, std::string > EnumValue
Enum payload: (numeric_value, label) so JSON output is human-readable while the integer is the canoni...
bool operator!=(const DIFF_VALUE &aOther) const
const Storage & GetStorage() const
std::vector< std::vector< std::vector< VECTOR2I > > > PolygonSet
DISPLAY_HINT m_displayHint
Presentation aid only; excluded from operator== and JSON (see DISPLAY_HINT).
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
Definition kiid.h:44
static KIID FromDeterministicString(const wxString &aName)
Build a deterministic UUID from an arbitrary name string.
Definition kiid.cpp:295
EDA_UNITS
Definition eda_units.h:44
#define KICOMMON_API
Definition kicommon.h:27
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
CHANGE_KIND
Coarse classification of a single item-level change between two documents.
const wxString DOC_PROP_ERC_SEVERITIES
const KIID & SchScreenSentinelKiid()
Sentinel KIID appended to a sheet's KIID_PATH to mark a per-sheet SCH_SCREEN resolution (page format ...
const wxString DOC_PROP_SYM_LIB_TABLE
bool ChangeInvalidatesZone(const ITEM_CHANGE &aChange)
Whether a change to an item of the given type invalidates any overlapping filled zones.
const wxString DOC_PROP_BOARD_THICKNESS
CHANGE_KIND ChangeKindFromString(const std::string &aKind)
const wxString DOC_PROP_PAGE_FORMAT
Property-name keys for the synthetic document-level ITEM_CHANGE (empty KIID_PATH).
bool WriteDiffOutput(const std::string &aContent, const wxString &aOutputPath)
Write diff/merge text output to aOutputPath, or to stdout when the path is empty.
const wxString DOC_PROP_NET_CLASSES
std::string SummarizeSeverities(const SeverityMap &aMap)
Format a severity-override map (DRC or ERC, keyed by error code, value is a SEVERITY enum) as a short...
const wxString DOC_PROP_CUSTOM_RULES
const wxString DOC_PROP_PAGE_ORIENTATION
const wxString DOC_PROP_FP_LIB_TABLE
KIID_PATH LibraryItemKiidPath(const wxString &aName)
Build a deterministic synthetic KIID_PATH from a library item name (symbol name or footprint name).
const wxString DOC_PROP_LAYER_STACKUP
const wxString DOC_PROP_DRAWING_SHEET
DISPLAY_HINT
How a numeric DIFF_VALUE should be interpreted when rendered for humans.
@ COORD
Coordinate in internal units (PT_COORD)
@ DISTANCE
Length in internal units (PT_SIZE)
@ ANGLE
Angle in degrees (PT_DEGREE)
bool ChangeRequiresConnectivityRebuild(const ITEM_CHANGE &aChange)
Whether a change to an item of the given type requires the connectivity graph to be rebuilt.
const wxString DOC_PROP_DRC_SEVERITIES
const char * ChangeKindToString(CHANGE_KIND aKind)
std::map< KIID_PATH, const ITEM_CHANGE * > IndexChangesByKiid(const DOCUMENT_DIFF &aDiff)
Flatten a DOCUMENT_DIFF's ITEM_CHANGE tree into a KIID_PATH -> ITEM_CHANGE* map, recursing into child...
std::string FormatDiffAsText(const DOCUMENT_DIFF &aDiff, const wxString &aLabelA, const wxString &aLabelB, EDA_UNITS aUnits, const EDA_IU_SCALE &aScale)
Render a DOCUMENT_DIFF as the human-readable text report shared by the diff jobs and CLI: a diff <lab...
std::map< wxString, const PROPERTY_DELTA * > IndexPropertiesByName(const ITEM_CHANGE &aChange)
Index property deltas inside one ITEM_CHANGE by property name.
STL namespace.
The full set of changes between two parsed documents of one type.
std::vector< ITEM_CHANGE > changes
One change record on a single item.
static ITEM_CHANGE FromJson(const nlohmann::json &aJson)
std::vector< PROPERTY_DELTA > properties
std::optional< wxString > refdes
std::vector< ITEM_CHANGE > children
nlohmann::json ToJson() const
Aggregated project-level diff covering many documents.
nlohmann::json ToJson() const
std::vector< DOCUMENT_DIFF > documents
static PROJECT_DIFF FromJson(const nlohmann::json &aJson)
Single (name, before, after) triple for one mutated property on an item.
static PROPERTY_DELTA FromJson(const nlohmann::json &aJson)
nlohmann::json ToJson() const
std::string path
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683