sanitize node names

This commit is contained in:
Bane Stojkovic
2026-09-07 12:30:37 +02:00
parent 37a5acce32
commit b7c707e68a
3 changed files with 74 additions and 1 deletions
@@ -72,6 +72,7 @@ public class NetlistBuilder {
if (!(c instanceof IContinuity && !(c instanceof ISwitch)) && !(c instanceof ICommonNode)) {
// regular components, create a node per control point
for (int i = 0; i < c.getControlPointCount(); i++) {
// Node renders the name through Node.sanitizeNodeName; here it only marks a named point
String nodeName = c.getControlPointNodeName(i);
if (c.isControlPointSticky(i) && nodeName != null
&& (!includeSwitches || !ISwitch.class.isAssignableFrom(type.getInstanceClass()))) {
@@ -52,7 +52,28 @@ public class Node implements Comparable<Node> {
}
public String getDisplayName() {
return component.getControlPointNodeName(pointIndex);
return sanitizeNodeName(component.getControlPointNodeName(pointIndex));
}
/**
* Strips the parenthesized annotation off a raw control point name, so a netlist reads
* <code>MCU1.D11</code> rather than <code>MCU1.D11 (~, MOSI)</code>. The bare name identifies the
* pin; everything in parentheses documents its alternate functions and only adds noise here.
*
* <p>A trailing disambiguator such as the <code>_1</code> in <code>GND_1</code> is deliberately
* kept, because those mark genuinely different pins that a netlist has to tell apart.
*
* @param nodeName raw name from {@link IDIYComponent#getControlPointNodeName(int)}
* @return the sanitized name, or null if the raw name was null
*/
public static String sanitizeNodeName(String nodeName) {
if (nodeName == null) {
return null;
}
int parenIndex = nodeName.indexOf('(');
String sanitized = (parenIndex == -1 ? nodeName : nodeName.substring(0, parenIndex)).trim();
// Never let sanitizing leave a pin nameless
return sanitized.isEmpty() ? nodeName.trim() : sanitized;
}
public Point2D getPoint2D() {
@@ -0,0 +1,51 @@
/*
*
* DIY Layout Creator (DIYLC).
* Copyright (c) 2009-2025 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.diylc.netlist;
import org.junit.Assert;
import org.junit.Test;
public class NodeNameTest {
@Test
public void testSanitizeNodeName() {
// The annotation in parentheses is stripped, the pin name is kept
Assert.assertEquals("D11", Node.sanitizeNodeName("D11 (~, MOSI)"));
Assert.assertEquals("A5", Node.sanitizeNodeName("A5 (SCL)"));
Assert.assertEquals("D3", Node.sanitizeNodeName("D3 (~)"));
Assert.assertEquals("VIN", Node.sanitizeNodeName("VIN (3.6-5.5V)"));
Assert.assertEquals("GPIO2/SDA", Node.sanitizeNodeName("GPIO2/SDA (Pin 3)"));
// Names without an annotation are untouched
Assert.assertEquals("VIN", Node.sanitizeNodeName("VIN"));
Assert.assertEquals("Tip", Node.sanitizeNodeName("Tip"));
Assert.assertEquals("3.3V", Node.sanitizeNodeName("3.3V"));
// Trailing disambiguators stay: these mark genuinely different pins
Assert.assertEquals("GND_1", Node.sanitizeNodeName("GND_1"));
Assert.assertEquals("5V_ICSP", Node.sanitizeNodeName("5V_ICSP"));
// Degenerate input never leaves a pin nameless
Assert.assertEquals("(only annotation)", Node.sanitizeNodeName("(only annotation)"));
Assert.assertNull(Node.sanitizeNodeName(null));
}
}