JsonLikeSyntaxAdapter (Project project) { return new JsonLikeSyntaxAdapter() { private final YAMLElementGenerator myGenerator = YAMLElementGenerator.getInstance(project); @Nullable @Override public PsiElement getPropertyValue(PsiElement property) { assert property instanceof YAMLKeyValue; YAMLValue value = ((YAMLKeyValue)property).getValue(); if (value == null) return null; return adjustValue(value); } @NotNull @Override public PsiElement adjustValue(@NotNull PsiElement value) { if (!(value instanceof YAMLValue)) return value; YAMLAnchor[] anchors = PsiTreeUtil.getChildrenOfType(value, YAMLAnchor.class); if (anchors == null || anchors.length == 0) return value; PsiElement next = PsiTreeUtil.skipWhitespacesAndCommentsForward(anchors[anchors.length - 1]); return next == null ? value : next; } @Nullable @Override public String getPropertyName(PsiElement property) { assert property instanceof YAMLKeyValue; return ((YAMLKeyValue)property).getName(); } private static YAMLKeyValue findPrecedingKeyValueWithNoValue(PsiElement element) { if (PsiUtilCore.getElementType(element) == YAMLTokenTypes.INDENT) { PsiElement prev = element.getPrevSibling(); prev = prev == null ? null : PsiTreeUtil.skipWhitespacesAndCommentsBackward(prev); if (prev instanceof YAMLKeyValue && ((YAMLKeyValue)prev).getValue() == null) { return (YAMLKeyValue)prev; } } return null; } @NotNull @Override public PsiElement createProperty(@NotNull String name, @NotNull String value, PsiElement element) { YAMLKeyValue keyValue = myGenerator.createYamlKeyValue(name, StringUtil.unquoteString(value)); return element instanceof YAMLDocument || findPrecedingKeyValueWithNoValue(element) != null ? myGenerator.createDummyYamlWithText(keyValue.getText()).getDocuments().get(0).getFirstChild() : keyValue; } @Override public boolean ensureComma(PsiElement self, PsiElement newElement) { if (newElement instanceof YAMLKeyValue && self instanceof YAMLKeyValue) { self.getParent().addAfter(myGenerator.createEol(), self); } return false; } @Override public void removeIfComma(PsiElement forward) { if (forward instanceof LeafPsiElement && ((LeafPsiElement)forward).getElementType() == YAMLTokenTypes.EOL) { PsiElement nextSibling; while ((nextSibling = forward.getNextSibling()) instanceof LeafPsiElement && ((LeafPsiElement)nextSibling).getElementType() == YAMLTokenTypes.INDENT) { nextSibling.delete(); } forward.delete(); } } @Override public boolean fixWhitespaceBefore(PsiElement initialElement, PsiElement element) { return initialElement instanceof YAMLValue && initialElement != element; } @NotNull @Override public String getDefaultValueFromType(@Nullable JsonSchemaType type) { if (type == null) return ""; if (type == JsonSchemaType._object) return " "; if (type == JsonSchemaType._array) return " - "; return type.getDefaultValue(); } @Override public PsiElement adjustNewProperty(PsiElement element) { if (element instanceof YAMLMapping) return element.getFirstChild(); return element; } @Override public PsiElement adjustPropertyAnchor(LeafPsiElement element) { YAMLKeyValue keyValue = findPrecedingKeyValueWithNoValue(element); assert keyValue != null : "Should come here only for YAMLKeyValue with no value and a following indent"; PsiComment nextComment = ObjectUtils.tryCast(skipNonNewlineSpaces(keyValue), PsiComment.class); if (nextComment != null) { keyValue.addBefore(myGenerator.createSpace(), null); keyValue.addBefore(nextComment.copy(), null); } keyValue.addBefore(myGenerator.createEol(), null); keyValue.addBefore(myGenerator.createIndent(element.getTextLength()), null); PsiElement prev = element.getPrevSibling(); if (prev != null) prev.delete(); element.delete(); if (nextComment != null) nextComment.delete(); return keyValue; } @Nullable private static PsiElement skipNonNewlineSpaces(YAMLKeyValue keyValue) { PsiElement sibling = keyValue.getNextSibling(); while (sibling instanceof PsiWhiteSpace && !sibling.getText().contains("\n")) { sibling = sibling.getNextSibling(); } return sibling; } }; }