Bug 577119 - Expressions does not work when records defined as inner classes are used Eclipse tries to parse the source code with a parser which only supports Java 1.4, so it fails to detect the 'records' coming from Java 17. This prevents using the 'Expression' view when the class contains inner record classes, and there are local variables with that type Change-Id: I38ec4f6f1ffc66c67807fcdc064a9cf8c4353e19 Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.debug/+/187494 Tested-by: JDT Bot <jdt-bot@eclipse.org> Reviewed-by: Sarika Sinha <sarika.sinha@in.ibm.com>
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java index 7e1848a..26e65b9 100644 --- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java +++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
@@ -305,7 +305,7 @@ private void createEvaluationSourceFromSource(String source, IType type, int line, boolean createInAStaticMethod, IJavaProject project) throws DebugException { - ASTParser parser = ASTParser.newParser(AST.JLS4); + ASTParser parser = ASTParser.newParser(AST.getJLSLatest()); parser.setSource(source.toCharArray()); Map<String, String> options = getCompilerOptions(project); String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java index 6dae414..d53d0fb 100644 --- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java +++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/SourceBasedSourceGenerator.java
@@ -92,6 +92,7 @@ import org.eclipse.jdt.core.dom.PrimitiveType; import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.jdt.core.dom.QualifiedType; +import org.eclipse.jdt.core.dom.RecordDeclaration; import org.eclipse.jdt.core.dom.ReturnStatement; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SimpleType; @@ -454,6 +455,11 @@ .equals(fLastTypeName)) { source.append(buildEnumDeclaration(null, enumDeclaration)); } + } else if (bodyDeclaration instanceof RecordDeclaration) { + var recordDeclaration = (RecordDeclaration) bodyDeclaration; + if (!recordDeclaration.getName().getIdentifier().equals(fLastTypeName)) { + source.append(buildRecordDeclaration(null, recordDeclaration)); + } } } return source; @@ -534,16 +540,14 @@ appendExtraDimensions(source, methodDeclaration.getExtraDimensions()); first = true; - for (Iterator<Name> iterator = methodDeclaration.thrownExceptions() - .iterator(); iterator.hasNext();) { - Name name = iterator.next(); + for (Object exceptionType : methodDeclaration.thrownExceptionTypes()) { if (first) { first = false; source.append(" throws "); //$NON-NLS-1$ } else { source.append(','); } - source.append(getQualifiedIdentifier(name)); + source.append(getTypeName((Type) exceptionType)); } if (Flags.isAbstract(modifiers) || Flags.isNative(modifiers)) { @@ -610,7 +614,71 @@ source.append(typeDeclaration.getName().getIdentifier()); - List<TypeParameter> typeParameters = typeDeclaration.typeParameters(); + buildTypeParameterList(source, typeDeclaration.typeParameters()); + + Type superClass = typeDeclaration.getSuperclassType(); + if (superClass != null) { + source.append(" extends "); //$NON-NLS-1$ + source.append(getTypeName(superClass)); + } + + buildSuperInterfaceTypeList(source, typeDeclaration.superInterfaceTypes().iterator(), typeDeclaration.isInterface()); + + if (buffer != null) { + fSnippetStartPosition += source.length(); + } + source.append(buildTypeBody(buffer, typeDeclaration.bodyDeclarations())); + + return source; + } + + void buildSuperInterfaceTypeList(StringBuilder source, Iterator<Type> superInterfaceTypes, boolean isTypeInterface) { + if (superInterfaceTypes.hasNext()) { + if (isTypeInterface) { + source.append(" extends "); //$NON-NLS-1$ + } else { + source.append(" implements "); //$NON-NLS-1$ + } + source.append(getTypeName(superInterfaceTypes.next())); + while (superInterfaceTypes.hasNext()) { + source.append(','); + source.append(getTypeName(superInterfaceTypes.next())); + } + } + } + + private StringBuilder buildRecordDeclaration(StringBuilder buffer, RecordDeclaration typeDeclaration) { + + StringBuilder source = new StringBuilder(); + source.append(Flags.toString(typeDeclaration.getModifiers())); + source.append(" record "); //$NON-NLS-1$ + + source.append(typeDeclaration.getName().getIdentifier()); + + buildTypeParameterList(source, typeDeclaration.typeParameters()); + + boolean first = true; + source.append('('); + for (SingleVariableDeclaration field : (List<SingleVariableDeclaration>) typeDeclaration.recordComponents()) { + if (first) { + first = false; + } else { + source.append(','); + } + source.append(getTypeName(field.getType())).append(' ').append(field.getName()); + } + source.append(')'); + buildSuperInterfaceTypeList(source, typeDeclaration.superInterfaceTypes().iterator(), false); + + if (buffer != null) { + fSnippetStartPosition += source.length(); + } + source.append(buildTypeBody(buffer, typeDeclaration.bodyDeclarations())); + + return source; + } + + void buildTypeParameterList(StringBuilder source, List<TypeParameter> typeParameters) { if (!typeParameters.isEmpty() && isSourceLevelGreaterOrEqual(1, 5)) { source.append('<'); Iterator<TypeParameter> iter = typeParameters.iterator(); @@ -643,33 +711,6 @@ } source.append('>'); } - - Type superClass = typeDeclaration.getSuperclassType(); - if (superClass != null) { - source.append(" extends "); //$NON-NLS-1$ - source.append(getTypeName(superClass)); - } - - Iterator<Type> iter = typeDeclaration.superInterfaceTypes().iterator(); - if (iter.hasNext()) { - if (typeDeclaration.isInterface()) { - source.append(" extends "); //$NON-NLS-1$ - } else { - source.append(" implements "); //$NON-NLS-1$ - } - source.append(getTypeName(iter.next())); - while (iter.hasNext()) { - source.append(','); - source.append(getTypeName(iter.next())); - } - } - - if (buffer != null) { - fSnippetStartPosition += source.length(); - } - source.append(buildTypeBody(buffer, typeDeclaration.bodyDeclarations())); - - return source; } private StringBuilder buildCompilationUnit(StringBuilder buffer, @@ -813,7 +854,7 @@ } return name; } else if (type.isArrayType()) { - return getTypeName(((ArrayType) type).getComponentType()) + "[]"; //$NON-NLS-1$ + return getTypeName(((ArrayType) type).getElementType()) + "[]"; //$NON-NLS-1$ } else if (type.isPrimitiveType()) { return ((PrimitiveType) type).getPrimitiveTypeCode().toString(); } else if (type.isQualifiedType()) { @@ -1091,7 +1132,6 @@ */ @Override public void endVisit(TypeDeclaration node) { - if (hasError()) { fTypeParameterStack.pop(); fTypeParameterTypeStack.pop();