31#include <drc_rules_lexer.h>
40wxString formatLayerClause(
const wxString& aLayerSource )
42 if( aLayerSource.IsEmpty() )
45 if( aLayerSource == DRC_RULES_LEXER::TokenName( DRCRULE_T::T_outer )
46 || aLayerSource == DRC_RULES_LEXER::TokenName( DRCRULE_T::T_inner ) )
47 return wxString::Format( wxS(
"(layer %s)" ), aLayerSource );
61 const std::vector<DRC_RE_LOADED_PANEL_ENTRY>& aEntries,
64 wxFFile file( aPath,
"w" );
66 if( !file.IsOpened() )
70 file.Write( content );
80 wxString
result =
"(version 1)\n";
85 using GroupKey = std::tuple<wxString, wxString, wxString>;
87 std::vector<std::pair<GroupKey, std::vector<const DRC_RE_LOADED_PANEL_ENTRY*>>>
89 std::map<GroupKey, size_t> groupIndex;
93 auto key = std::make_tuple( entry.ruleName, entry.condition, entry.layerSource );
94 auto it = groupIndex.find( key );
96 if( it == groupIndex.end() )
98 groupIndex[key] = groupedEntries.size();
99 groupedEntries.push_back( { key, { &entry } } );
103 groupedEntries[it->second].second.push_back( &entry );
108 for(
const auto& [key, entries] : groupedEntries )
112 if( entries.size() == 1 )
123 if( !ruleText.IsEmpty() )
124 result += ruleText +
"\n";
132 const BOARD* aBoard )
140 return wxEmptyString;
158 silkCond = wxS(
"L == 'F.Mask'" );
160 silkCond = wxS(
"L == 'B.Mask'" );
162 silkCond = wxS(
"L == 'F.Mask' || L == 'B.Mask'" );
174 silkCond = wxS(
"L == 'F.SilkS'" );
176 silkCond = wxS(
"L == 'B.SilkS'" );
178 silkCond = wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" );
202 if( !severityClause.IsEmpty() && !ruleText.Contains(
"(severity" ) )
205 size_t lastParen = ruleText.rfind(
')' );
207 if( lastParen != wxString::npos )
209 ruleText = ruleText.Left( lastParen ) +
"\n\t" + severityClause +
")";
220 if( !aBoard || !aLayers.any() )
221 return wxEmptyString;
224 return wxString::Format( wxS(
"(layer %s)" ), DRC_RULES_LEXER::TokenName( DRCRULE_T::T_outer ) );
227 return wxString::Format( wxS(
"(layer %s)" ), DRC_RULES_LEXER::TokenName( DRCRULE_T::T_inner ) );
232 return wxString::Format( wxS(
"(layer \"%s\")" ), aBoard->
GetLayerName( layer ) );
234 return wxEmptyString;
246 default:
return wxEmptyString;
252 const std::vector<const DRC_RE_LOADED_PANEL_ENTRY*>& aEntries,
253 const BOARD* aBoard )
255 if( aEntries.empty() )
256 return wxEmptyString;
260 bool allUnedited =
true;
262 for(
const auto* entry : aEntries )
264 if( entry->wasEdited )
271 if( allUnedited && !aEntries[0]->originalRuleText.IsEmpty() )
272 return aEntries[0]->originalRuleText;
283 for(
const auto* entry : aEntries )
285 if( entry->layerCondition.any() && aBoard )
287 if( !entry->layerSource.IsEmpty() )
288 ctx.
layerClause = formatLayerClause( entry->layerSource );
297 std::vector<wxString> allClauses;
299 for(
const auto* entry : aEntries )
301 if( entry->constraintData )
304 entryCtx.
ruleName = entry->ruleName;
306 entryCtx.
constraintCode = entry->constraintData->GetConstraintCode();
308 auto clauses = entry->constraintData->GetConstraintClauses( entryCtx );
310 for(
const wxString& clause : clauses )
312 if( !clause.IsEmpty() )
313 allClauses.push_back( clause );
324 rule << wxS(
"\t" ) << ctx.
layerClause << wxS(
"\n" );
326 for(
const wxString& clause : allClauses )
327 rule << wxS(
"\t" ) << clause << wxS(
"\n" );
331 rule << wxS(
"\t(condition \"" )
336 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 sanitizeRuleName(const wxString &aRuleName)
Sanitize a rule name for use in S-expression output.
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.