Skip to content

Commit ef59011

Browse files
committed
resolve white space preservation when generating CMakeLists.txt
1 parent 2764dac commit ef59011

33 files changed

+1318
-202
lines changed

VERSION.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
### Version History
66
- [CLionArduinoPlugin Version Notes](#clionarduinoplugin-version-notes)
77
- [TO DO](#to-do)
8-
- [1.5.24 Next](#1524-next)
8+
- [1.5.26 Next](#1526-next)
99
- [1.5.11](#1511)
1010
- [1.5.9](#159)
1111
- [1.5.7](#157)
@@ -52,8 +52,13 @@
5252
* Add: inspection to check that `CMakeLists.txt` is out of sync, especially if missing the
5353
toolchain file.
5454

55-
### 1.5.24 Next
55+
### 1.5.26 Next
5656

57+
* Fix: resolve white space preservation in regenerated `CMakeLists.txt` file. Only changing text
58+
for values which were changed.
59+
* Fix: `CMakeLists.txt` file with mixed project macro name when `PROJECT_NAME` or
60+
`CMAKE_PROJECT_NAME` is used to set `_SRCS` and `_HDRS`, while project was set with another
61+
macro name, for example `project(${ANOTHER_NAME})`
5762
* Fix: disable diff buttons if the toolchain file is not `ArduinoToolchain.cmake` so that other
5863
toolchain files will not be erroneously compared to bundled version.
5964
* Fix: add second diff button for toolchain diff viewing `Platform/Arduino.cmake`

src/com/vladsch/clionarduinoplugin/generators/ArduinoProjectGenerator.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,6 @@ abstract class ArduinoProjectGenerator(isLibrary: Boolean) : CMakeProjectGenerat
369369
// JTextField field = ((TextFieldWithBrowseButton) jcomp).getTextField();
370370
// String text = field.getText();
371371
// field.setText(text);
372-
// int tmp = 0;
373372
// }
374373
// showChildTree((JComponent) comp, lvl + "." + i);
375374
// }

src/com/vladsch/clionarduinoplugin/generators/cmake/ArduinoCMakeListsTxtBuilder.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ class ArduinoCMakeListsTxtBuilder : CMakeListsTxtBuilder {
7777
// if command is not found or has less args then an empty value will be used
7878
//
7979

80-
8180
// @formatter:off
8281
val GENERATE_ARDUINO_FIRMWARE = CMakeCommandType("GENERATE_ARDUINO_FIRMWARE", "generate_arduino_firmware", arrayOf(), 1, 1, true, false, true, arrayOf("\${PROJECT_NAME}"), 0)
8382
val GENERATE_ARDUINO_LIBRARY = CMakeCommandType("GENERATE_ARDUINO_LIBRARY", "generate_arduino_library", arrayOf(), 1, 1, true, false, true, arrayOf("\${PROJECT_NAME}"), 0)
@@ -260,7 +259,6 @@ class ArduinoCMakeListsTxtBuilder : CMakeListsTxtBuilder {
260259

261260
val baudRateText = appSettings.baudRateText
262261
builder.setOrAddCommand(SET_UPLOAD_SPEED, baudRateText.ifEmpty("9600")).setSuppressible(baudRateText.isEmpty())
263-
// builder.removeCommand(SET_UPLOAD_SPEED)
264262

265263
builder.setOrAddCommand(SET_AFLAGS, "-v").setSuppressible(!appSettings.isVerbose)
266264

@@ -273,7 +271,7 @@ class ArduinoCMakeListsTxtBuilder : CMakeListsTxtBuilder {
273271
}
274272

275273
// Can add our own values to resolve variables
276-
// TODO: figure out how to make comments unused false make sense with comments above
274+
277275
return builder.getCMakeContents(
278276
null,
279277
!appSettings.isCommentUnusedSettings,
@@ -315,8 +313,8 @@ class ArduinoCMakeListsTxtBuilder : CMakeListsTxtBuilder {
315313
val cMakeProjectName = builder.cMakeProjectName
316314

317315
settings.projectName = cMakeProjectName ?: ""
318-
settings.sources = cMakeVariableValues["\${PROJECT_NAME}_SRCS"].toTypedArray()
319-
settings.headers = cMakeVariableValues["\${PROJECT_NAME}_HDRS"].toTypedArray()
316+
settings.sources = cMakeVariableValues["${builder.cMakeProjectNameMacro}_SRCS"].toTypedArray()
317+
settings.headers = cMakeVariableValues["${builder.cMakeProjectNameMacro}_HDRS"].toTypedArray()
320318
settings.sketch = cMakeVariableValues["${cMakeProjectName}_SKETCH"].firstOrNull() ?: ""
321319
settings.boardId = cMakeVariableValues["${cMakeProjectName}_BOARD"].firstOrNull() ?: ""
322320
settings.cpuId = cMakeVariableValues["ARDUINO_CPU"].firstOrNull() ?: ""

src/com/vladsch/clionarduinoplugin/generators/cmake/CMakeFormatter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.vladsch.clionarduinoplugin.generators.cmake.ast.CMakeFile;
55
import com.vladsch.clionarduinoplugin.generators.cmake.ast.LineEnding;
66
import com.vladsch.flexmark.formatter.*;
7-
import com.vladsch.flexmark.formatter.FormatterOptions;
87
import com.vladsch.flexmark.html.renderer.HtmlIdGenerator;
98
import com.vladsch.flexmark.html.renderer.LinkType;
109
import com.vladsch.flexmark.html.renderer.ResolvedLink;
@@ -41,6 +40,8 @@
4140

4241
import static com.vladsch.flexmark.formatter.Formatter.NULL_ITERABLE;
4342

43+
// TODO: add a node post processor to move nodes between if() ... else() ... endif() to be child nodes of if() and else() with block wrapper around them
44+
// otherwise indentation will not work because all commands are at the root level.
4445
public class CMakeFormatter implements IRender {
4546

4647
// syntax options

src/com/vladsch/clionarduinoplugin/generators/cmake/CMakeListsTxtBuilder.kt

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
package com.vladsch.clionarduinoplugin.generators.cmake
22

33
import com.intellij.openapi.diagnostic.Logger
4-
import com.vladsch.clionarduinoplugin.generators.cmake.ast.Argument
5-
import com.vladsch.clionarduinoplugin.generators.cmake.ast.BlankLine
6-
import com.vladsch.clionarduinoplugin.generators.cmake.ast.CMakeFile
7-
import com.vladsch.clionarduinoplugin.generators.cmake.ast.Command
8-
import com.vladsch.clionarduinoplugin.generators.cmake.ast.CommentedOutCommand
9-
import com.vladsch.clionarduinoplugin.generators.cmake.ast.LineComment
4+
import com.vladsch.clionarduinoplugin.generators.cmake.ast.*
105
import com.vladsch.clionarduinoplugin.generators.cmake.commands.*
116
import com.vladsch.clionarduinoplugin.resources.TemplateResolver
127
import com.vladsch.clionarduinoplugin.resources.resolveRefs
@@ -210,10 +205,11 @@ abstract class CMakeListsTxtBuilder(
210205
if (rawArgs.size > 1) cMakeVariableValues[rawArgs[0]] = rawArgs.slice(1 .. rawArgs.size - 1)
211206
else cMakeVariableValues[rawArgs[0]] = null
212207
} else if (rawArgs.isNotEmpty() && (rawArgs[0] == "\${PROJECT_NAME}_SRCS" || rawArgs[0] == "\${PROJECT_NAME}_HDRS"
213-
|| rawArgs[0] == "\${CMAKE_PROJECT_NAME}_SRCS" || rawArgs[0] == "\${CMAKE_PROJECT_NAME}_HDRS")) {
208+
|| rawArgs[0] == "\${CMAKE_PROJECT_NAME}_SRCS" || rawArgs[0] == "\${CMAKE_PROJECT_NAME}_HDRS")
209+
) {
214210
// this is most likely a mistake, since the project name is in cMakeProjectNameMacro
215211
val replaceMacroName = cMakeProjectNameMacro + rawArgs[0].substring(rawArgs[0].length - 5)
216-
if (rawArgs.size > 1) cMakeVariableValues[replaceMacroName] = rawArgs.slice(1 .. rawArgs.size - 1)
212+
if (rawArgs.size > 1) cMakeVariableValues[replaceMacroName] = rawArgs.slice(1 .. rawArgs.size - 1)
217213
else cMakeVariableValues[replaceMacroName] = null
218214
} else {
219215
if (args.size > 1) cMakeVariableValues[useVarName ?: args[0]] = args.slice(1 .. args.size - 1)
@@ -264,15 +260,24 @@ abstract class CMakeListsTxtBuilder(
264260
// find the command or we can create a new one if we don't have it already or just make it into a text block
265261
var commandType: CMakeCommandType? = null
266262
val rawArgs = ArrayList<String>()
267-
val rawArgLeadingSpaces = ArrayList<BasedSequence>()
263+
val rawArgsLeadingSpaces = ArrayList<BasedSequence>()
268264

269265
for (arg in node.getChildren()) {
270266
if (arg is Argument) {
271267
rawArgs.add(arg.text.toString())
272-
rawArgLeadingSpaces.add(arg.leadingSpaces)
268+
if (arg.previous is LineEnding) {
269+
rawArgsLeadingSpaces.add(arg.leadingSpaces.prefixWithEOL())
270+
} else {
271+
rawArgsLeadingSpaces.add(arg.leadingSpaces)
272+
}
273273
}
274274
}
275275

276+
val lastChild = node.lastChild
277+
val addBeforeClosing =
278+
if (lastChild is LineEnding) node.baseSubSequence(lastChild.startOffset, node.closingMarker.startOffset)
279+
else BasedSequence.NULL
280+
276281
val commandName = node.command.toString()
277282
if (commandName == "set") {
278283
// see if we have a matching set command
@@ -336,11 +341,10 @@ abstract class CMakeListsTxtBuilder(
336341
if (commandName == "made_up_command") {
337342
val tmp = 0
338343
}
339-
344+
340345
if (commandType != null) {
341-
makeCommand = CMakeCommand(commandType, node.next is LineComment)
342-
// KLUDGE: blank line nodes steal EOL from next node's leadingSpaces, so need to add it here to compensate
343-
makeCommand.leadingSpaces = if (node.previous is BlankLine) node.leadingSpaces.prefixWithEOL() else node.leadingSpaces
346+
makeCommand = CMakeCommand(commandType, false, addBeforeClosing)
347+
makeCommand.leadingSpaces = node.leadingSpaces
344348

345349
var i = 0
346350
var j = 0
@@ -353,20 +357,19 @@ abstract class CMakeListsTxtBuilder(
353357
val matcher = regEx.matcher(rawArgs[i++])
354358
matcher.find()
355359
for (g in 1 .. matcher.groupCount()) {
356-
makeCommand.setArg(j++, matcher.group(g), rawArgLeadingSpaces[g])
360+
makeCommand.setArg(j++, matcher.group(g), rawArgsLeadingSpaces[g])
357361
}
358362
} else i++
359363
}
360364

361365
while (i < rawArgs.size) {
362-
makeCommand.setArg(j++, rawArgs[i], rawArgLeadingSpaces[i])
366+
makeCommand.setArg(j++, rawArgs[i], rawArgsLeadingSpaces[i])
363367
i++
364368
}
365369
} else {
366370
// unknown command
367-
makeCommand = CMakeUnknownCommand(commandName, rawArgs, rawArgLeadingSpaces, node.next is LineComment)
368-
// KLUDGE: blank line nodes steal EOL from next node's leadingSpaces, so need to add it here to compensate
369-
makeCommand.leadingSpaces = if (node.previous is BlankLine) node.leadingSpaces.prefixWithEOL() else node.leadingSpaces
371+
makeCommand = CMakeUnknownCommand(commandName, rawArgs, rawArgsLeadingSpaces, false, addBeforeClosing)
372+
makeCommand.leadingSpaces = node.leadingSpaces
370373
}
371374

372375
if (node is CommentedOutCommand) {
@@ -377,9 +380,7 @@ abstract class CMakeListsTxtBuilder(
377380
}
378381

379382
// create a text element
380-
// KLUDGE: blank line nodes steal EOL from next node's leadingSpaces, so need to add it here to compensate
381-
// however, if the previous is a LineComment and it has EOL then adding an extra one would double blank lines
382-
return CMakeText(node.chars.toString(), node is BlankLine && node.next !is BlankLine && node.next !is Command && !(node.previous is LineComment && node.previous?.chars?.endsWithEOL()?:false))
383+
return CMakeText(node.chars.toString(), false)
383384
}
384385

385386
fun elementOriginalText(element: CMakeElement): String {
@@ -437,7 +438,7 @@ abstract class CMakeListsTxtBuilder(
437438
}
438439

439440
fun removeElement(index: Int) {
440-
if (index + 1 < myElements.size)
441+
if (index + 1 < myElements.size)
441442
myElements[index + 1].isAddEOL = myElements[index].isAddEOL
442443
myElements.removeAt(index)
443444
}
@@ -802,7 +803,7 @@ abstract class CMakeListsTxtBuilder(
802803
val command = setCommand(commandType, args)
803804
if (command == null) {
804805
// create a new one and find where to insert it
805-
val newCommand = CMakeCommand(commandType, args?.toList() ?: listOf(), null, true)
806+
val newCommand = CMakeCommand(commandType, args?.toList() ?: listOf(), null, true, BasedSequence.NULL)
806807
addCommand(newCommand)
807808
return newCommand
808809
}
@@ -842,13 +843,19 @@ abstract class CMakeListsTxtBuilder(
842843
if (commandType.isNoDupeArgs) {
843844
// add another one after this one if the arg value is different
844845
if (!command.allArgsEqual(argList)) {
845-
newCommand = CMakeCommand(command.commandType, argList, command.getArgsLeadingSpaces(argList), true)
846+
newCommand = CMakeCommand(
847+
command.commandType,
848+
argList,
849+
command.getArgsLeadingSpaces(argList),
850+
true,
851+
command.addBeforeClosing
852+
)
846853
newCommand.commentOut(false)
847854
addElementAfter(command, newCommand)
848855
}
849856
} else {
850857
// add another one after this one
851-
newCommand = CMakeCommand(command.commandType, argList, null, true)
858+
newCommand = CMakeCommand(command.commandType, argList, null, true, BasedSequence.NULL)
852859
addElementAfter(command, newCommand)
853860
}
854861
} else {
@@ -866,7 +873,7 @@ abstract class CMakeListsTxtBuilder(
866873
replaceElement(command, newCommand)
867874
} else {
868875
// is a matched sub-type, need to replace completely
869-
newCommand = CMakeCommand(commandType, argList, null, false)
876+
newCommand = CMakeCommand(commandType, argList, null, false, command.addBeforeClosing)
870877
newCommand.commentOut(false)
871878
newCommand.setArgsWithDefaults(argList, command.getArgsLeadingSpaces(argList))
872879

@@ -1082,7 +1089,7 @@ abstract class CMakeListsTxtBuilder(
10821089
private val LOG = Logger.getInstance("com.vladsch.clionarduinoplugin.generators")
10831090
private val DEFAULT_OPTIONS = MutableDataSet()
10841091
.set(CMakeParser.AUTO_CONFIG, true)
1085-
.set(CMakeParser.AST_LINE_END_EOL, false)
1092+
.set(CMakeParser.AST_LINE_END_EOL, true)
10861093
.set(CMakeParser.AST_COMMENTS, true)
10871094
.set(CMakeParser.AST_BLANK_LINES, true)
10881095
.set(CMakeParser.AST_ARGUMENT_SEPARATORS, true)

src/com/vladsch/clionarduinoplugin/generators/cmake/CMakeNodeFormatter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ private void render(final Command node, final NodeFormatterContext context, fina
5757
markdown.append("# ");
5858
}
5959
}
60+
if (formatterOptions.preserveWhitespace) {
61+
markdown.append(node.getLeadingSpaces());
62+
}
6063
markdown.append(node.getCommand());
6164
if (formatterOptions.preserveWhitespace) {
6265
CMakeFormatterContext.appendWhiteSpaceBetween(markdown, node.getCommand(), node.getOpeningMarker(), formatterOptions.preserveWhitespace, formatterOptions.collapseWhitespace, true);

src/com/vladsch/clionarduinoplugin/generators/cmake/CMakeParser.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,14 @@ protected boolean parseElement() {
190190
if (res) {
191191
// it is
192192
CommentedOutCommand node = (CommentedOutCommand) document.getLastChildAny(CommentedOutCommand.class);
193+
193194
if (node != null) {
194-
node.setLeadingSpaces(input.subSequence(start, saved));
195+
BasedSequence leadingSpaces = BasedSequence.NULL;
196+
if (node.getPrevious() != null) {
197+
// commented out nodes get their leading spaces from the start of comment
198+
leadingSpaces = input.subSequence(node.getPrevious().getEndOffset(), start);
199+
}
200+
node.setLeadingSpaces(leadingSpaces);
195201
node.setCommentMarker(input.subSequence(saved, saved + 1));
196202
node.setCharsFromContent();
197203
}
@@ -248,7 +254,12 @@ protected boolean parseCommandInvocation(Node parent, final boolean isCommentedO
248254

249255
if (parseLineEnding(parent, index)) {
250256
// we are good
251-
commandNode.setLeadingSpaces(input.subSequence(start, command.getEndOffset()));
257+
BasedSequence leadingSpaces = BasedSequence.NULL;
258+
if (!isCommentedOut && commandNode.getPrevious() != null) {
259+
// commented out nodes get their leading spaces from the start of comment
260+
leadingSpaces = input.subSequence(commandNode.getPrevious().getEndOffset(), saved);
261+
}
262+
commandNode.setLeadingSpaces(leadingSpaces);
252263
commandNode.setCommand(command);
253264
commandNode.setOpeningMarker(open);
254265
commandNode.setArguments(input.subSequence(open.getEndOffset(), close.getStartOffset()));

src/com/vladsch/clionarduinoplugin/generators/cmake/ast/Argument.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ public Argument(final BasedSequence chars, final BasedSequence openingMarker, fi
2121
this.text = text;
2222
this.closingMarker = closingMarker;
2323
}
24+
25+
public BasedSequence getLeadingSpaces() {
26+
Node previous = getPrevious();
27+
int startOffset = getStartOffset();
28+
29+
if (previous == null) {
30+
if (getParent() instanceof Command) {
31+
startOffset = ((Command) getParent()).getOpeningMarker().getEndOffset();
32+
}
33+
} else {
34+
startOffset = previous.getEndOffset();
35+
}
36+
37+
return baseSubSequence(startOffset, getStartOffset());
38+
}
2439

2540
@Override
2641
public BasedSequence[] getSegments() {

src/com/vladsch/clionarduinoplugin/generators/cmake/ast/Command.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.vladsch.clionarduinoplugin.generators.cmake.ast;
22

33
import com.vladsch.flexmark.util.ast.Node;
4+
import com.vladsch.flexmark.util.misc.CharPredicate;
45
import com.vladsch.flexmark.util.sequence.BasedSequence;
56

67
public class Command extends Node {
@@ -34,8 +35,12 @@ public void getAstExtra(StringBuilder out) {
3435
public BasedSequence getLeadingSpaces() {
3536
return leadingSpaces;
3637
}
37-
38-
public void setLeadingSpaces(final BasedSequence leadingSpaces) {
38+
39+
public void setLeadingSpaces(BasedSequence leadingSpaces) {
40+
// need to trim spaces before EOL, these are previous node's trailing spaces
41+
if (leadingSpaces.indexOf('\n') > 0) {
42+
leadingSpaces = leadingSpaces.subSequence(leadingSpaces.countLeading(CharPredicate.SPACE_TAB));
43+
}
3944
this.leadingSpaces = leadingSpaces.isEmpty() ? BasedSequence.NULL : leadingSpaces;
4045
}
4146

0 commit comments

Comments
 (0)