in gradle-dsl-groovy/src/com/android/tools/idea/gradle/dsl/parser/groovy/GroovyDslWriter.java [130:280]
public PsiElement createDslElement(@NotNull GradleDslElement element) {
if (element instanceof GradleDslInfixExpression) return createDslInfixExpression((GradleDslInfixExpression) element);
GroovyPsiElement psiElement = ensureGroovyPsi(element.getPsiElement());
if (psiElement != null) {
return psiElement;
}
GradleDslAnchor anchorAfter = element.getAnchor();
if (anchorAfter == null) {
return null;
}
boolean addBefore = false;
if (element.isNewEmptyBlockElement()) {
return null; // Avoid creation of an empty block statement.
}
// If the parent doesn't have a psi element, the anchor will be used to create the parent in getParentPsi.
// In this case we want to be placed in the newly made parent so we ignore our anchor.
GradleDslElement dslParent = anchorAfter.getParentDslElement();
if (dslParent == null) return null;
if (needToCreateParent(dslParent)) {
addBefore = true;
anchorAfter = new GradleDslAnchor.Start(dslParent);
}
PsiElement parentPsiElement = getParentPsi(dslParent);
if (parentPsiElement == null) return null;
Project project = parentPsiElement.getProject();
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
ExternalNameInfo externalNameInfo = maybeTrimForParent(element, this);
String statementText = quotePartsIfNecessary(externalNameInfo);
assert !statementText.isEmpty() : "Element name can't be empty! This will cause statement creation to error.";
ExternalNameSyntax syntax = externalNameInfo.syntax;
switch (syntax) {
case UNKNOWN: syntax = element.getExternalSyntax(); break;
default: element.setExternalSyntax(syntax);
}
if (element.isBlockElement()) {
if (element instanceof MavenRepositoryDslElement && element.getContainedElements(true).isEmpty()) {
statementText += "()";
}
else {
statementText += " {\n}\n";
}
}
else if (syntax == ASSIGNMENT || syntax == AUGMENTED_ASSIGNMENT || syntax == SET_METHOD) {
if (element.getElementType() == PropertyType.REGULAR) {
switch (syntax) {
case ASSIGNMENT: statementText += " = 'abc'"; break;
case AUGMENTED_ASSIGNMENT: statementText += " += 'abc'"; break;
case SET_METHOD: statementText += ".set('abc')"; break;
}
}
else if (element.getElementType() == PropertyType.VARIABLE) {
statementText = "def " + statementText + " = 'abc'";
}
}
else {
statementText += " \"abc\", \"xyz\"";
}
GrStatement statement = factory.createStatementFromText(statementText);
// TODO: Move these workarounds to a more sensible way of doing things.
if (statement instanceof GrApplicationStatement applicationStatement) {
// Workaround to create an application statement.
applicationStatement.getArgumentList().delete();
}
else if (statement instanceof GrAssignmentExpression assignment) {
// Workaround to create an assignment statement
if (assignment.getRValue() != null) {
assignment.getRValue().delete();
}
}
else if (statement instanceof GrVariableDeclaration variableDeclaration) {
for (GrVariable var : variableDeclaration.getVariables()) {
if (var.getInitializerGroovy() != null) {
var.getInitializerGroovy().delete();
// The '=' gets deleted here, add it back.
final ASTNode node = var.getNode();
node.addLeaf(mASSIGN, "=", var.getLastChild().getNode().getTreeNext());
}
}
}
else if (syntax == SET_METHOD && statement instanceof GrMethodCallExpression methodCallExpression) {
methodCallExpression.getArgumentList().delete();
}
PsiElement lineTerminator = factory.createLineTerminator(1);
PsiElement addedElement;
PsiElement anchor = getPsiElementForAnchor(parentPsiElement, anchorAfter);
if (parentPsiElement instanceof GroovyFile) {
// Check if the file has a Block Comment and add the psi element after it if true.
PsiElement firstFileChild = parentPsiElement.getFirstChild();
if (addBefore) {
// should really do this for all kinds of parentPsiElement, not just GroovyFile
addedElement = parentPsiElement.addBefore(statement, anchor);
}
else if (firstFileChild != null && firstFileChild.getNode().getElementType() == ML_COMMENT && anchor == null) {
addedElement = parentPsiElement.addAfter(statement, firstFileChild);
}
else {
addedElement = parentPsiElement.addAfter(statement, anchor);
}
if (!isWhiteSpaceOrNls(addedElement.getPrevSibling())) {
parentPsiElement.addBefore(lineTerminator, addedElement);
}
if (addBefore) {
parentPsiElement.addAfter(lineTerminator, addedElement);
}
}
else if (parentPsiElement instanceof GrClosableBlock) {
addedElement = parentPsiElement.addAfter(statement, anchor);
PsiElement prevSibling = addedElement.getPrevSibling();
if (!(anchorAfter instanceof GradleDslAnchor.Start)) {
if (!(prevSibling instanceof GrParameterList)) {
parentPsiElement.addBefore(lineTerminator, addedElement);
}
}
else {
parentPsiElement.addAfter(lineTerminator, addedElement);
if (closableBlockNeedsNewline((GrClosableBlock)parentPsiElement)) {
parentPsiElement.addBefore(lineTerminator, addedElement);
}
}
}
else {
addedElement = parentPsiElement.addAfter(statement, anchor);
parentPsiElement.addBefore(lineTerminator, addedElement);
}
if (element.isBlockElement()) {
GrClosableBlock closableBlock = getClosableBlock(addedElement);
if (closableBlock != null) {
element.setPsiElement(closableBlock);
}
}
else {
if (addedElement instanceof GrApplicationStatement ||
addedElement instanceof GrAssignmentExpression ||
addedElement instanceof GrVariableDeclaration) {
// This is for the workarounds above, this ensures that applyDslLiteral is called to actually add the value to
// either the application or assignment statement.
element.setPsiElement(addedElement);
}
else if (syntax == SET_METHOD && addedElement instanceof GrMethodCallExpression) {
element.setPsiElement(addedElement);
}
}
return element.getPsiElement();
}