Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CSharp implementation of proposed NamingService #25

Merged
merged 6 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.csharp.service;

import org.openrewrite.internal.NameCaseConvention;
import org.openrewrite.internal.NamingService;

import java.util.regex.Pattern;

public class CSharpNamingService implements NamingService {

private static final Pattern STANDARD_METHOD_NAME = Pattern.compile("^[A-Z][a-zA-Z0-9]*$");
private static final Pattern SNAKE_CASE = Pattern.compile("^[a-zA-Z0-9]+_\\w+$");
Comment on lines +25 to +26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We made some changes in openrewrite/rewrite#4725 ; might be best to similarly test here that we use C# expected naming from a few valid but odd inputs in a unit test.


@Override
public String standardizeMethodName(String oldMethodName) {
if (!STANDARD_METHOD_NAME.matcher(oldMethodName).matches()) {
StringBuilder result = new StringBuilder();
if (SNAKE_CASE.matcher(oldMethodName).matches()) {
result.append(NameCaseConvention.format(NameCaseConvention.UPPER_CAMEL, oldMethodName));
} else {
int nameLength = oldMethodName.length();
for (int i = 0; i < nameLength; i++) {
char c = oldMethodName.charAt(i);
if (i == 0) {
// the java specification requires identifiers to start with [a-zA-Z$_]
if (c != '$' && c != '_') {
result.append(Character.toUpperCase(c));
}
} else {
if (!Character.isLetterOrDigit(c)) {
while ((!Character.isLetterOrDigit(c) || c > 'z')) {
i++;
if (i < nameLength) {
c = oldMethodName.charAt(i);
} else {
break;
}
}
if (i < nameLength) {
result.append(Character.toUpperCase(c));
}
} else {
result.append(c);
}
}
}
}
return result.toString();
}
return oldMethodName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NullMarked
@NonNullFields
package org.openrewrite.csharp.service;

import org.jspecify.annotations.NullMarked;
import org.openrewrite.internal.lang.NonNullFields;
79 changes: 39 additions & 40 deletions rewrite-csharp/src/main/java/org/openrewrite/csharp/tree/Cs.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import org.openrewrite.*;
import org.openrewrite.csharp.CSharpPrinter;
import org.openrewrite.csharp.CSharpVisitor;
import org.openrewrite.csharp.service.CSharpNamingService;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.internal.NamingService;
import org.openrewrite.java.JavaPrinter;
import org.openrewrite.java.JavaTypeVisitor;
import org.openrewrite.java.internal.TypesInUse;
Expand Down Expand Up @@ -72,7 +74,7 @@ final class CompilationUnit implements Cs, JavaSourceFile {

@Nullable
@NonFinal
transient WeakReference<Padding> padding;
transient WeakReference<Padding> padding;

@Getter
@With
Expand Down Expand Up @@ -264,8 +266,17 @@ public Padding getPadding() {
return p;
}

@Override
@Incubating(since = "8.2.0")
public <S, T extends S> T service(Class<S> service) {
if (NamingService.class.getName().equals(service.getName())) {
return (T) new CSharpNamingService();
}
return JavaSourceFile.super.service(service);
}

@RequiredArgsConstructor
public static class Padding implements JavaSourceFile.Padding {
public static class Padding implements JavaSourceFile.Padding {
private final Cs.CompilationUnit t;

@Override
Expand Down Expand Up @@ -505,7 +516,9 @@ final class Argument implements Cs, Expression {
@With
Keyword refKindKeyword;

public @Nullable Identifier getNameColumn() { return nameColumn == null ? null : nameColumn.getElement(); }
public @Nullable Identifier getNameColumn() {
return nameColumn == null ? null : nameColumn.getElement();
}

public Argument withNameColumn(@Nullable Identifier nameColumn) {
return getPadding().withNameColumn(JRightPadded.withElement(this.nameColumn, nameColumn));
Expand Down Expand Up @@ -1602,7 +1615,7 @@ public <P> J acceptCSharp(CSharpVisitor<P> v, P p) {
return v.visitInterpolation(this, p);
}

public Padding getPadding() {
public Padding getPadding() {
Padding p;
if (this.padding == null) {
p = new Padding(this);
Expand Down Expand Up @@ -1966,7 +1979,7 @@ public PropertyDeclaration withType(@Nullable JavaType type) {
}

public @Nullable NameTree getInterfaceSpecifier() {
return interfaceSpecifier!= null ? interfaceSpecifier.getElement() : null;
return interfaceSpecifier != null ? interfaceSpecifier.getElement() : null;
}

public PropertyDeclaration withInterfaceSpecifier(@Nullable NameTree interfaceSpecifier) {
Expand Down Expand Up @@ -2058,14 +2071,11 @@ public PropertyDeclaration withInitializer(@Nullable JLeftPadded<Expression> ini
}
}



@Getter
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
@RequiredArgsConstructor
final class Keyword implements Cs
{
final class Keyword implements Cs {
@With
@Getter
@EqualsAndHashCode.Include
Expand All @@ -2088,8 +2098,7 @@ final class Keyword implements Cs
return v.visitKeyword(this, p);
}

public enum KeywordKind
{
public enum KeywordKind {
Ref,
Out,
Await,
Expand Down Expand Up @@ -2145,7 +2154,7 @@ public CoordinateBuilder.Statement getCoordinates() {

@Override
public Cs.Lambda withType(@Nullable JavaType type) {
return this.getType() == type ? this : new Cs.Lambda(
return this.getType() == type ? this : new Cs.Lambda(
id,
prefix,
markers,
Expand Down Expand Up @@ -2491,12 +2500,13 @@ public TypeParameterConstraintClause withTypeParameterConstraints(@Nullable JCon
}
}

interface TypeParameterConstraint extends J {}
interface TypeParameterConstraint extends J {
}

/**
* Represents a type constraint in a type parameter's constraint clause.
* Example: where T : SomeClass
* where T : IInterface
* where T : IInterface
*/
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
Expand Down Expand Up @@ -2573,10 +2583,8 @@ public TypeConstraint withType(TypeTree type) {

/* ------------------ */




interface AllowsConstraint extends J {}
interface AllowsConstraint extends J {
}

/**
* Represents an `allows` constraint in a where clause.
Expand Down Expand Up @@ -2701,8 +2709,7 @@ final class ClassOrStructConstraint implements Cs, TypeParameterConstraint {
@Getter
TypeKind kind;

public enum TypeKind
{
public enum TypeKind {
Class,
Struct
}
Expand Down Expand Up @@ -2788,7 +2795,6 @@ public <P> J acceptCSharp(CSharpVisitor<P> v, P p) {
* // use result
* }
* </pre>
*
* Example 2: Deconstruction declaration:
* <pre>
* int (x, y) = point;
Expand Down Expand Up @@ -2852,9 +2858,11 @@ public CoordinateBuilder.Expression getCoordinates() {
}

//region VariableDesignation

/**
* Interface for variable designators in declaration expressions.
* This can be either a single variable name or a parenthesized list of designators for deconstruction.
*
* @see SingleVariableDesignation
* @see ParenthesizedVariableDesignation
*/
Expand All @@ -2864,12 +2872,10 @@ interface VariableDesignation extends Expression, Cs {
/**
* Represents a single variable declaration within a declaration expression.
* Used both for simple out variable declarations and as elements within deconstruction declarations.
*
* Example in out variable:
* <pre>
* int.TryParse(s, out int x) // 'int x' is the SingleVariable
* </pre>
*
* Example in deconstruction:
* <pre>
* (int x, string y) = point; // both 'int x' and 'string y' are SingleVariables
Expand Down Expand Up @@ -2908,7 +2914,7 @@ public <P> J acceptCSharp(CSharpVisitor<P> v, P p) {

@Override
public SingleVariableDesignation withType(@Nullable JavaType type) {
return this.getType() == type ? this : new SingleVariableDesignation(
return this.getType() == type ? this : new SingleVariableDesignation(
id,
prefix,
markers,
Expand All @@ -2924,12 +2930,10 @@ public CoordinateBuilder.Expression getCoordinates() {

/**
* Represents a parenthesized list of variable declarations used in deconstruction patterns.
*
* Example of simple deconstruction:
* <pre>
* int (x, y) = point;
* </pre>
*
* Example of nested deconstruction:
* <pre>
* (int count, var (string name, int age)) = GetPersonDetails();
Expand Down Expand Up @@ -3413,15 +3417,13 @@ public Cs.Unary withOperator(JLeftPadded<Type> operator) {
/**
* Represents a constructor initializer which is a call to another constructor, either in the same class (this)
* or in the base class (base).
*
* Examples:
* <pre>
* <pre>
* class Person {
* // Constructor with 'this' initializer
* public Person(string name) : this(name, 0) { }
*
* // Constructor with 'base' initializer
* public Person(string name, int age) : base(name) { }
* // Constructor with 'this' initializer
* public Person(string name) : this(name, 0) { }
* // Constructor with 'base' initializer
* public Person(string name, int age) : base(name) { }
* }
* </pre>
*/
Expand Down Expand Up @@ -3701,6 +3703,7 @@ public CoordinateBuilder.Statement getCoordinates() {
}

}

/**
* Represents an initializer expression that consists of a list of expressions, typically used in array
* or collection initialization contexts. The expressions are contained within delimiters like curly braces.
Expand Down Expand Up @@ -4157,6 +4160,7 @@ public IsPattern withPattern(JLeftPadded<Pattern> pattern) {
}

//region Patterns

/**
* Base interface for all C# pattern types that can appear on the right-hand side of an 'is' expression.
* This includes type patterns, constant patterns, declaration patterns, property patterns, etc.
Expand Down Expand Up @@ -4709,6 +4713,7 @@ public ListPattern withPatterns(JContainer<Pattern> patterns) {

}
}

/**
* Represents a C# parenthesized pattern expression that groups a nested pattern.
* <p>
Expand Down Expand Up @@ -5274,8 +5279,6 @@ public CoordinateBuilder.Expression getCoordinates() {

}



/**
* Represents a property pattern clause in C# pattern matching, which matches against object properties.
* <p>
Expand Down Expand Up @@ -5863,8 +5866,7 @@ public SwitchSection withStatements(List<JRightPadded<Statement>> statements) {
}
}

public interface SwitchLabel extends Expression
{
public interface SwitchLabel extends Expression {

}

Expand Down Expand Up @@ -6371,8 +6373,6 @@ final class FixedStatement implements Cs, Statement {
@Getter
J.Block block;



@Override
public <P> J acceptCSharp(CSharpVisitor<P> v, P p) {
return v.visitFixedStatement(this, p);
Expand All @@ -6385,7 +6385,6 @@ public CoordinateBuilder.Statement getCoordinates() {
}
}


/**
* Represents a C# checked statement which enforces overflow checking for arithmetic operations
* and conversions. Operations within a checked block will throw OverflowException if arithmetic
Expand Down
Loading
Loading