27#include <drc_rules_lexer.h>
36wxString formatLayerClause(
const wxString& aLayerSource )
38 if( aLayerSource.IsEmpty() )
41 if( aLayerSource == DRC_RULES_LEXER::TokenName( DRCRULE_T::T_outer )
42 || aLayerSource == DRC_RULES_LEXER::TokenName( DRCRULE_T::T_inner ) )
43 return wxString::Format( wxS(
"(layer %s)" ), aLayerSource );
57 const std::vector<DRC_RE_LOADED_PANEL_ENTRY>& aEntries,
61 std::string utf8 = std::string( content.mb_str( wxConvUTF8 ) );
70 wxString
result =
"(version 2)\n";
75 using GroupKey = std::tuple<wxString, wxString, wxString>;
77 std::vector<std::pair<GroupKey, std::vector<const DRC_RE_LOADED_PANEL_ENTRY*>>>
79 std::map<GroupKey, size_t> groupIndex;
83 auto key = std::make_tuple( entry.ruleName, entry.condition, entry.layerSource );
84 auto it = groupIndex.find( key );
86 if( it == groupIndex.end() )
88 groupIndex[key] = groupedEntries.size();
89 groupedEntries.push_back( { key, { &entry } } );
93 groupedEntries[it->second].second.push_back( &entry );
98 for(
const auto& [key, entries] : groupedEntries )
102 if( entries.size() == 1 )
113 if( !ruleText.IsEmpty() )
114 result += ruleText +
"\n";
122 const BOARD* aBoard )
130 return wxEmptyString;
148 silkCond = wxS(
"L == 'F.Mask'" );
150 silkCond = wxS(
"L == 'B.Mask'" );
152 silkCond = wxS(
"L == 'F.Mask' || L == 'B.Mask'" );
164 silkCond = wxS(
"L == 'F.SilkS'" );
166 silkCond = wxS(
"L == 'B.SilkS'" );
168 silkCond = wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" );
192 if( !severityClause.IsEmpty() && !ruleText.Contains(
"(severity" ) )
195 size_t lastParen = ruleText.rfind(
')' );
197 if( lastParen != wxString::npos )
199 ruleText = ruleText.Left( lastParen ) +
"\n\t" + severityClause +
")";
210 if( !aBoard || !aLayers.any() )
211 return wxEmptyString;
214 return wxString::Format( wxS(
"(layer %s)" ), DRC_RULES_LEXER::TokenName( DRCRULE_T::T_outer ) );
217 return wxString::Format( wxS(
"(layer %s)" ), DRC_RULES_LEXER::TokenName( DRCRULE_T::T_inner ) );
222 return wxString::Format( wxS(
"(layer \"%s\")" ), aBoard->
GetLayerName( layer ) );
224 return wxEmptyString;
236 default:
return wxEmptyString;
242 const std::vector<const DRC_RE_LOADED_PANEL_ENTRY*>& aEntries,
243 const BOARD* aBoard )
245 if( aEntries.empty() )
246 return wxEmptyString;
250 bool allUnedited =
true;
252 for(
const auto* entry : aEntries )
254 if( entry->wasEdited )
261 if( allUnedited && !aEntries[0]->originalRuleText.IsEmpty() )
262 return aEntries[0]->originalRuleText;
273 for(
const auto* entry : aEntries )
275 if( entry->layerCondition.any() && aBoard )
277 if( !entry->layerSource.IsEmpty() )
278 ctx.
layerClause = formatLayerClause( entry->layerSource );
287 std::vector<wxString> allClauses;
289 for(
const auto* entry : aEntries )
291 if( entry->constraintData )
294 entryCtx.
ruleName = entry->ruleName;
296 entryCtx.
constraintCode = entry->constraintData->GetConstraintCode();
298 auto clauses = entry->constraintData->GetConstraintClauses( entryCtx );
300 for(
const wxString& clause : clauses )
302 if( !clause.IsEmpty() )
303 allClauses.push_back( clause );
314 rule << wxS(
"\t" ) << ctx.
layerClause << wxS(
"\n" );
316 for(
const wxString& clause : allClauses )
317 rule << wxS(
"\t" ) << clause << wxS(
"\n" );
321 rule << wxS(
"\t(condition \"" )
326 for(
const auto* entry : aEntries )
Information pertinent to a Pcbnew printed circuit board.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
wxString GetConstraintCode() const
static wxString formatRuleName(const wxString &aRuleName)
Format a rule name for use in S-expression output while preserving the exact name the user chose.
virtual wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext)
wxString GetGeneratedRule() const
bool SaveFile(const wxString &aPath, const std::vector< DRC_RE_LOADED_PANEL_ENTRY > &aEntries, const BOARD *aBoard=nullptr)
Save all panel entries to a file.
wxString generateLayerClause(const LSET &aLayers, const BOARD *aBoard)
Generate a layer clause from an LSET.
wxString generateRuleText(const DRC_RE_LOADED_PANEL_ENTRY &aEntry, const BOARD *aBoard)
Generate the rule text for a single panel entry.
wxString GenerateRulesText(const std::vector< DRC_RE_LOADED_PANEL_ENTRY > &aEntries, const BOARD *aBoard=nullptr)
Generate rule text from panel entries.
wxString generateMergedRuleText(const std::vector< const DRC_RE_LOADED_PANEL_ENTRY * > &aEntries, const BOARD *aBoard)
Generate a merged rule text from multiple panel entries with the same name/condition.
wxString generateSeverityClause(SEVERITY aSeverity)
Generate a severity clause.
LSET is a set of PCB_LAYER_IDs.
static const LSET & ExternalCuMask()
Return a mask holding the Front and Bottom layers.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
wxString GetComment()
Get the comment associated with the rule.
@ SILK_TO_SOLDERMASK_CLEARANCE
PCB_LAYER_ID
A quick note on layer IDs:
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
Represents a rule loaded from a .kicad_dru file and mapped to a panel.
wxString originalRuleText
wxString layerSource
Original layer text: "inner", "outer", or layer name.
std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > constraintData
DRC_RULE_EDITOR_CONSTRAINT_NAME panelType
wxString conditionExpression
wxString result
Test unit parsing edge cases and error handling.