Skip to content

Commit

Permalink
Introduce basic DOM models and converter code to avoid errors in editor.
Browse files Browse the repository at this point in the history
  • Loading branch information
jarthana committed Nov 4, 2023
1 parent 843a49f commit e4b399a
Show file tree
Hide file tree
Showing 8 changed files with 559 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,7 @@ public void testParenthesizedExpression() {
ParenthesizedExpression x1 = this.ast.newParenthesizedExpression();
basicMatch(x1);
}
@SuppressWarnings("deprecation")
public void testPatternInstanceofExpression() {
if (this.ast.apiLevel() < AST.JLS17) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.TemplateExpression;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
Expand Down Expand Up @@ -2074,13 +2073,49 @@ public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expre
if (expression instanceof org.eclipse.jdt.internal.compiler.ast.SwitchExpression) {
return convert((org.eclipse.jdt.internal.compiler.ast.SwitchExpression) expression);
}
if (expression instanceof TemplateExpression) {
if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TemplateExpression) {
return convert((org.eclipse.jdt.internal.compiler.ast.TemplateExpression) expression);
}
if (expression instanceof org.eclipse.jdt.internal.compiler.ast.StringTemplate) {
return convert((org.eclipse.jdt.internal.compiler.ast.StringTemplate) expression);
}
return null;
}
public Expression convert(org.eclipse.jdt.internal.compiler.ast.TemplateExpression expression) {
return convert(expression.processor);
StringTemplateExpression templateExpr = new StringTemplateExpression(this.ast);
if (this.resolveBindings) {
recordNodes(templateExpr, expression);
}
templateExpr.setProcessor(convert(expression.processor));
templateExpr.setTemplate(convert(expression.template));

int startPosition = expression.sourceStart;
int sourceEnd= expression.sourceEnd;
templateExpr.setSourceRange(startPosition, sourceEnd - startPosition + 1);
return templateExpr;
}
public StringTemplate convert(org.eclipse.jdt.internal.compiler.ast.StringTemplate template) {
StringTemplate strTemplate = new StringTemplate(this.ast);
if (this.resolveBindings) {
recordNodes(strTemplate, template);
}
List<Expression> fragments = strTemplate.fragments();
for (org.eclipse.jdt.internal.compiler.ast.StringLiteral fragment : template.fragments()) {
if (fragment instanceof org.eclipse.jdt.internal.compiler.ast.TextBlock) {
fragments.add(convert((org.eclipse.jdt.internal.compiler.ast.TextBlock) fragment));
} else {
fragments.add(convert(fragment));
}
}
List<Expression> expressions = strTemplate.expressions();
for (org.eclipse.jdt.internal.compiler.ast.Expression exp : template.values()) {
expressions.add(convert(exp));
}

int startPosition = template.sourceStart;
int sourceEnd= template.sourceEnd;
strTemplate.setSourceRange(startPosition, sourceEnd - startPosition + 1);
return strTemplate;
}
public StringLiteral convert(org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral expression) {
expression.computeConstant();
Expand Down Expand Up @@ -2274,9 +2309,9 @@ public Pattern convert(org.eclipse.jdt.internal.compiler.ast.RecordPattern patte
} else if (pattern.type != null) {
recordPattern.setPatternType(convertType(pattern.type));
}
List<Pattern> patterns = recordPattern.patterns();
for (org.eclipse.jdt.internal.compiler.ast.Pattern nestedPattern : pattern.patterns ) {
recordPattern.patterns().add(convert(nestedPattern));

patterns.add(convert(nestedPattern));
}
return recordPattern;
}
Expand Down
53 changes: 53 additions & 0 deletions org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,7 @@ public boolean match(ParenthesizedExpression node, Object other) {
* different node type or is <code>null</code>
* @since 3.26
*/
@SuppressWarnings("deprecation")
public boolean match(PatternInstanceofExpression node, Object other) {
if (!(other instanceof PatternInstanceofExpression)) {
return false;
Expand Down Expand Up @@ -3177,4 +3178,56 @@ public boolean match(YieldStatement node, Object other) {
return safeSubtreeMatch(node.getExpression(), o.getExpression());
}

/**
* Returns whether the given node and the other object match.
* <p>
* The default implementation provided by this class tests whether the
* other object is a node of the same type with structurally isomorphic
* child subtrees. Subclasses may override this method as needed.
* </p>
*
* @since 3.36
*
* @param node the node
* @param other the other object, or <code>null</code>
* @return <code>true</code> if the subtree matches, or
* <code>false</code> if they do not match or the other object has a
* different node type or is <code>null</code>
* @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
*/
public boolean match(StringTemplateExpression node, Object other) {
if (!(other instanceof StringTemplateExpression)) {
return false;
}
StringTemplateExpression o = (StringTemplateExpression) other;
return safeSubtreeMatch(node.getProcessor(), o.getProcessor()) &&
safeSubtreeMatch(node.getTemplate(), o.getTemplate());
}

/**
* Returns whether the given node and the other object match.
* <p>
* The default implementation provided by this class tests whether the
* other object is a node of the same type with structurally isomorphic
* child subtrees. Subclasses may override this method as needed.
* </p>
*
* @since 3.36
*
* @param node the node
* @param other the other object, or <code>null</code>
* @return <code>true</code> if the subtree matches, or
* <code>false</code> if they do not match or the other object has a
* different node type or is <code>null</code>
* @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
*/
public boolean match(StringTemplate node, Object other) {
if (!(other instanceof StringTemplate)) {
return false;
}
StringTemplate o = (StringTemplate) other;
return safeSubtreeListMatch(node.fragments(), o.fragments()) &&
safeSubtreeListMatch(node.expressions(), o.expressions());
}

}
16 changes: 16 additions & 0 deletions org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,22 @@ public abstract class ASTNode {
* @noreference This field is not intended to be referenced by clients.
*/
public static final int ENHANCED_FOR_WITH_RECORD_PATTERN = 114;
/**
* Node type constant indicating a node of type
* <code>StringTemplate</code>.
* @see org.eclipse.jdt.internal.compiler.ast.StringTemplate
* @since 3.36
* @noreference This field is not intended to be referenced by clients.
*/
public static final int STRING_TEMPLATE = 115;
/**
* Node type constant indicating a node of type
* <code>StringTemplateExpression</code>.
* @see org.eclipse.jdt.internal.compiler.ast.TemplateExpression
* @since 3.36
* @noreference This field is not intended to be referenced by clients.
*/
public static final int STRING_TEMPLATE_EXPRESSION = 116;

/**
* Returns the node class for the corresponding node type.
Expand Down
47 changes: 47 additions & 0 deletions org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,40 @@ public boolean visit(WildcardType node) {
public boolean visit(YieldStatement node) {
return true;
}
/**
* Visits the given type-specific AST node.
* <p>
* The default implementation does nothing and returns true.
* Subclasses may reimplement.
* </p>
*
* @param node the node to visit
* @return <code>true</code> if the children of this node should be
* visited, and <code>false</code> if the children of this node should
* be skipped
* @since 3.36
* @noreference This method is not intended to be referenced by clients.
*/
public boolean visit(StringTemplateExpression node) {
return true;
}
/**
* Visits the given type-specific AST node.
* <p>
* The default implementation does nothing and returns true.
* Subclasses may reimplement.
* </p>
*
* @param node the node to visit
* @return <code>true</code> if the children of this node should be
* visited, and <code>false</code> if the children of this node should
* be skipped
* @since 3.36
* @noreference This method is not intended to be referenced by clients.
*/
public boolean visit(StringTemplate node) {
return true;
}

/**
* End of visit the given type-specific AST node.
Expand Down Expand Up @@ -3531,4 +3565,17 @@ public void endVisit(WildcardType node) {
public void endVisit(YieldStatement node) {
// default implementation: do nothing
}

/**
* @since 3.36
*/
public void endVisit(StringTemplateExpression expression) {
// default implementation: do nothing
}
/**
* @since 3.36
*/
public void endVisit(StringTemplate template) {
// default implementation: do nothing
}
}
167 changes: 167 additions & 0 deletions org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringTemplate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*******************************************************************************
* Copyright (c) 2023 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.jdt.core.dom;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil;

/**
* StringTemplateExpression AST node type.
*
* @since 3.36
* @noreference This class is not intended to be referenced by clients.
*/
@SuppressWarnings("rawtypes")
public class StringTemplate extends Expression {
/**
* A list of property descriptors (element type:
* {@link StructuralPropertyDescriptor}),
* or null if uninitialized.
*/
private static final List PROPERTY_DESCRIPTORS;
/**
* The "patterns" structural property of this node type (child type: {@link Pattern}).
*/
public static final ChildListPropertyDescriptor STRING_TEMPLATE_FRAGMENTS =
new ChildListPropertyDescriptor(StringTemplate.class, "fragments", Expression.class, CYCLE_RISK); //$NON-NLS-1$

/**
* The "patternType" structural property of this node type (child type: {@link Type}).
*/
public static final ChildListPropertyDescriptor STRING_TEMPLATE_VALUES =
new ChildListPropertyDescriptor(StringTemplate.class, "expressions", Expression.class, CYCLE_RISK); //$NON-NLS-1$

static {
List propertyList = new ArrayList(2);
createPropertyList(StringTemplate.class, propertyList);
addProperty(STRING_TEMPLATE_FRAGMENTS, propertyList);
addProperty(STRING_TEMPLATE_VALUES, propertyList);
PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
}

/**
*/
private final ASTNode.NodeList fragments =
new ASTNode.NodeList(STRING_TEMPLATE_FRAGMENTS);
/**
*/
private final ASTNode.NodeList expressions =
new ASTNode.NodeList(STRING_TEMPLATE_VALUES);

StringTemplate(AST ast) {
super(ast);
supportedOnlyIn21();
}

/**
* Returns a list of structural property descriptors for this node type.
* Clients must not modify the result.
*
* @param apiLevel the API level; one of the
* <code>AST.JLS*</code> constants
* @return a list of property descriptors (element type:
* {@link StructuralPropertyDescriptor})
* @since 3.24
*/
public static List propertyDescriptors(int apiLevel) {
return PROPERTY_DESCRIPTORS;
}
public static List propertyDescriptors(int apiLevel, boolean previewEnabled) {
if (DOMASTUtil.isStringTemplateSupported(apiLevel, previewEnabled)) {
return PROPERTY_DESCRIPTORS;
}
return null;
}
@Override
final List internalStructuralPropertiesForType(int apiLevel) {
return propertyDescriptors(apiLevel);
}

@Override
final List internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled) {
return propertyDescriptors(apiLevel, previewEnabled);
}
/**
* @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
*/
@SuppressWarnings("unchecked")
public List<Expression> fragments() {
supportedOnlyIn21();
return this.fragments;
}
@SuppressWarnings("unchecked")
public List<Expression> expressions() {
supportedOnlyIn21();
return this.expressions;
}
@Override
int getNodeType0() {
return STRING_TEMPLATE;
}

@Override
final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
if (property == STRING_TEMPLATE_FRAGMENTS) {
return fragments();
}
if (property == STRING_TEMPLATE_VALUES) {
return expressions();
}
// allow default implementation to flag the error
return super.internalGetChildListProperty(property);
}

@Override
boolean subtreeMatch0(ASTMatcher matcher, Object other) {
return matcher.match(this, other);
}

@Override
ASTNode clone0(AST target) {
StringTemplate result = new StringTemplate(target);
result.fragments().addAll(ASTNode.copySubtrees(target, fragments()));
result.expressions().addAll(ASTNode.copySubtrees(target, expressions()));
result.setSourceRange(getStartPosition(), getLength());
return result;
}

@Override
void accept0(ASTVisitor visitor) {
boolean visitChildren = visitor.visit(this);
if (visitChildren) {
// visit children in normal left to right reading order
acceptChildren(visitor, this.fragments);
acceptChildren(visitor, this.expressions);
}
visitor.endVisit(this);

}

@Override
int memSize() {
return BASE_NODE_SIZE + 2 * 4;
}

@Override
int treeSize() {
return
memSize()
+ this.fragments.listSize()
+ this.expressions.listSize();
}
}

0 comments on commit e4b399a

Please sign in to comment.