First things first, amazing work 馃憣 I'm really happy you built this.
That being said, there's one teensy tiny thing that I can't seem to get working.
Whenever I add properties _(or update using .set() with a new structure)_ all newlines are removed.
Here's a tiny example:
testrun.js
const {Project} = require('ts-simple-ast');
const project = new Project({
manipulationSettings: {
indentationText: ' '
}
});
project.addExistingSourceFiles('User.ts');
const f = project.getSourceFileOrThrow('User.ts');
const c = f.getClass('User');
const s = c.getStructure();
c.set({
properties: [
...s.properties,
{
name: "motto",
type: "string",
decorators: [
{
name: "field",
arguments: [`{ type: 'string' }`]
}
]
}
]
});
f.formatText();
project.save();
And the source file (User.ts) I'm manipulating:
import { field, autoFields, entity, Mapping, MetaData } from 'wetland';
@autoFields()
@entity()
export class User {
@field({ type: 'string' })
username: string;
@field({ type: 'string' })
password: string;
@field({ type: 'timestamp', nullable: true })
lastLogin: number;
}
After the save, I end up with the following:
import { field, autoFields, entity, Mapping, MetaData } from 'wetland';
@autoFields()
@entity()
export class User {
@field({ type: 'string' })
username: string;
@field({ type: 'string' })
password: string;
@field({ type: 'timestamp', nullable: true })
lastLogin: number;
@field({ type: 'string' })
motto: string;
}
The same happens when I simply use addProperty().
Again, thanks for your amazing work, this is allowing me to make better tools for our open source projects 馃檶
Update: I found writers, so I could write but I can't get in between properties when creating a class.
file.insertText(magicalNumberIHaveYetToFind, writer => writer.writeLine('\n));
So.. I could find the index and write a newline afterwards but I'm confident I'm just missing something.
Hey @RWOverdijk, right now the default setting between properties is for a newline and not a blank line. I'd have to either add a global manipulation setting to control spacing between properties and/or add another parameter to .addProperty-like methods that allows you to set the spacing.
For the time being, you could probably use the appendWhitespace or prependWhitespace method that exists on every node.
For example, I believe this will work (untested):
import { Node, TypeGuards } from "ts-simple-ast";
// ...etc...
const userClass = f.getClassOrThrow('User');
const lastMember = userClass.getMembers().pop();
const addedProperties = userClass.addProperties(...etc...);
// add an extra newline if the previous last member was a property
if (lastMember != null && TypeGuards.isPropertyDeclaration(lastMember))
appendNewLine(lastMember);
// append a newline to every added property, except the last one which is at the end of the class
addedProperties.slice(0, -1).forEach(appendNewLine);
function appendNewLine(node: Node) {
node.appendWhitespace(writer => writer.newLine());
}
That does work. Thanks. :)
@RWOverdijk cool. By the way, I just updated the code with something more robust. You may want to extract that out to a reusable function so it's not so painful for the time being.
@dsherret What do you mean? You want me to extract the update, or this snippet?
I meant you'd probably want to take that snippet and extract it out to a reusable function in your code for the time being. Something like this:
// untested
import { ClassDeclaration, PropertyDeclarationStructure } from "ts-simple-ast";
export function addPropertiesWithBlankLines(classDec: ClassDeclaration, properties: PropertyDeclarationStructure[]) {
const lastMember = classDec.getMembers().pop();
const addedProperties = classDec.addProperties(properties);
// add an extra newline if the previous last member was a property
if (lastMember != null && TypeGuards.isPropertyDeclaration(lastMember))
appendNewLine(lastMember);
// append a newline to every added property, except the last one which is at the end of the class
addedProperties.slice(0, -1).forEach(appendNewLine);
function appendNewLine(node: Node) {
node.appendWhitespace(writer => writer.newLine());
}
}
Ah! Yes that's exactly what I did.
classDeclaration
.addProperties(fields)
.slice(0, -1)
.forEach(p => p.appendWhitespace(writer => writer.newLine()));
In version 2 it will be possible to do the following:
classDec.addProperty({
leadingTrivia: writer => writer.newLine(),
name: "prop2"
});
This can be extracted out to a function:
function addLeadingNewline<T extends Structure>(structure: T) {
structure.leadingTrivia = writer => writer.newLine();
return structure;
}
I'd still like a global option to add blank lines between properties though.
I'm going to close this. If anyone wants to do this they can use the solution described above.
I don't believe I will be adding any more configuration for changing how the code looks. I'm currently developing a code formatter that will have a lot of configuration (https://github.com/dsherret/dprint) and that could be used with #664
Basically, it's extremely hard to get code formatting right and it's better for it to be its own dedicated thing and that will be what dprint is for.
Most helpful comment
Ah! Yes that's exactly what I did.