Skip to content

Commit

Permalink
Merge branch 'main' into groovy-parser-parenthesis-pt2
Browse files Browse the repository at this point in the history
  • Loading branch information
Laurens-W authored Dec 18, 2024
2 parents bd4ca6d + 65c9cf1 commit 69803b8
Show file tree
Hide file tree
Showing 40 changed files with 2,108 additions and 689 deletions.
61 changes: 0 additions & 61 deletions .github/workflows/receive-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,64 +17,3 @@ jobs:
uses: openrewrite/gh-automation/.github/workflows/receive-pr.yml@main
with:
recipe: 'org.openrewrite.recipes.OpenRewriteBestPracticesSubset'
rewrite_yml: |
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.recipes.OpenRewriteBestPracticesSubset
displayName: OpenRewrite best practices
description: Best practices for OpenRewrite recipe development.
recipeList:
- org.openrewrite.recipes.JavaRecipeBestPracticesSubset
- org.openrewrite.recipes.RecipeTestingBestPracticesSubset
- org.openrewrite.recipes.RecipeNullabilityBestPracticesSubset
#- org.openrewrite.java.OrderImports
- org.openrewrite.java.format.EmptyNewlineAtEndOfFile
- org.openrewrite.staticanalysis.InlineVariable
- org.openrewrite.staticanalysis.MissingOverrideAnnotation
- org.openrewrite.staticanalysis.UseDiamondOperator
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.recipes.JavaRecipeBestPracticesSubset
displayName: Java Recipe best practices
description: Best practices for Java recipe development.
preconditions:
- org.openrewrite.java.search.FindTypes:
fullyQualifiedTypeName: org.openrewrite.Recipe
checkAssignability: true
recipeList:
- org.openrewrite.java.recipes.BlankLinesAroundFieldsWithAnnotations
- org.openrewrite.java.recipes.ExecutionContextParameterName
- org.openrewrite.java.recipes.MissingOptionExample
- org.openrewrite.java.recipes.RecipeEqualsAndHashCodeCallSuper
- org.openrewrite.java.recipes.UseTreeRandomId
- org.openrewrite.staticanalysis.NeedBraces
#- org.openrewrite.staticanalysis.RemoveSystemOutPrintln
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.recipes.RecipeTestingBestPracticesSubset
displayName: Recipe testing best practices
description: Best practices for testing recipes.
preconditions:
- org.openrewrite.java.search.FindTypes:
fullyQualifiedTypeName: org.openrewrite.test.RewriteTest
checkAssignability: true
recipeList:
- org.openrewrite.java.recipes.RewriteTestClassesShouldNotBePublic
#- org.openrewrite.java.recipes.SelectRecipeExamples
- org.openrewrite.java.recipes.SourceSpecTextBlockIndentation
- org.openrewrite.java.testing.cleanup.RemoveTestPrefix
- org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic
- org.openrewrite.staticanalysis.NeedBraces
- org.openrewrite.staticanalysis.RemoveSystemOutPrintln
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.recipes.RecipeNullabilityBestPracticesSubset
displayName: Recipe nullability best practices
description: Use OpenRewrite internal nullability annotations; drop JetBrains annotations; use `package-info.java` instead.
recipeList:
- org.openrewrite.staticanalysis.NullableOnMethodReturnType
- org.openrewrite.java.RemoveAnnotation:
annotationPattern: '@org.jetbrains.annotations.NotNull'
- org.openrewrite.java.RemoveAnnotation:
annotationPattern: '@jakarta.annotation.Nonnull'
#- org.openrewrite.java.jspecify.MigrateToJspecify
4 changes: 0 additions & 4 deletions rewrite-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ dependencies {

api("org.jspecify:jspecify:latest.release")

// Pinning okhttp while waiting on 5.0.0
// https://github.com/openrewrite/rewrite/issues/1479
compileOnly("com.squareup.okhttp3:okhttp:4.9.3")

implementation("org.apache.commons:commons-compress:latest.release")

implementation("io.micrometer:micrometer-core:1.9.+")
Expand Down
61 changes: 43 additions & 18 deletions rewrite-core/src/main/java/org/openrewrite/GitRemote.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,51 +113,64 @@ public Parser() {
* @return the clone url
*/
public URI toUri(GitRemote remote, String protocol) {
return buildUri(remote.service, remote.origin, remote.path, protocol);
}

/**
* Build a {@link URI} clone url from components, if that protocol is supported (configured) by the matched server
*
* @param service the type of SCM service
* @param origin the origin of the SCM service, any protocol will be stripped (and not used for matching)
* @param path the path to the repository
* @param protocol the protocol to use. Supported protocols: ssh, http, https
* @return the clone URL if it could be created.
* @throws IllegalArgumentException if the protocol is not supported by the server.
*/
public URI buildUri(Service service, String origin, String path, String protocol) {
if (!ALLOWED_PROTOCOLS.contains(protocol)) {
throw new IllegalArgumentException("Invalid protocol: " + protocol + ". Must be one of: " + ALLOWED_PROTOCOLS);
}
URI selectedBaseUrl;

if (remote.service == Service.Unknown) {
if (PORT_PATTERN.matcher(remote.origin).find()) {
throw new IllegalArgumentException("Unable to determine protocol/port combination for an unregistered origin with a port: " + remote.origin);
if (service == Service.Unknown) {
if (PORT_PATTERN.matcher(origin).find()) {
throw new IllegalArgumentException("Unable to determine protocol/port combination for an unregistered origin with a port: " + origin);
}
selectedBaseUrl = URI.create(protocol + "://" + stripProtocol(remote.origin));
selectedBaseUrl = URI.create(protocol + "://" + stripProtocol(origin));
} else {
selectedBaseUrl = servers.stream()
.filter(server -> server.allOrigins()
.stream()
.anyMatch(origin -> origin.equalsIgnoreCase(stripProtocol(remote.origin)))
.anyMatch(o -> o.equalsIgnoreCase(stripProtocol(origin)))
)
.flatMap(server -> server.getUris().stream())
.filter(uri -> uri.getScheme().equals(protocol))
.filter(uri -> Parser.normalize(uri).getScheme().equals(protocol))
.findFirst()
.orElseGet(() -> {
URI normalizedUri = Parser.normalize(remote.origin);
URI normalizedUri = Parser.normalize(origin);
if (!normalizedUri.getScheme().equals(protocol)) {
throw new IllegalStateException("No matching server found that supports ssh for origin: " + remote.origin);
throw new IllegalArgumentException("Unable to build clone URL. No matching server found that supports " + protocol + " for origin: " + origin);
}
return normalizedUri;
});
}

String path = remote.path.replaceFirst("^/", "");
path = path.replaceFirst("^/", "");
boolean ssh = protocol.equals("ssh");
switch (remote.service) {
switch (service) {
case Bitbucket:
if (!ssh) {
path = "scm/" + remote.path;
path = "scm/" + path;
}
break;
case AzureDevOps:
if (ssh) {
path = "v3/" + remote.path;
path = "v3/" + path;
} else {
path = remote.path.replaceFirst("([^/]+)/([^/]+)/(.*)", "$1/$2/_git/$3");
path = path.replaceFirst("([^/]+)/([^/]+)/(.*)", "$1/$2/_git/$3");
}
break;
}
if (remote.service != Service.AzureDevOps) {
if (service != Service.AzureDevOps) {
path += ".git";
}
String maybeSlash = selectedBaseUrl.toString().endsWith("/") ? "" : "/";
Expand Down Expand Up @@ -203,11 +216,18 @@ public Parser registerRemote(Service service, String origin) {
return this;
}

/**
* Find a registered remote server by an origin.
*
* @param origin the origin of the server. Any protocol will be stripped (and not used to match)
* @return The server if found, or an unknown type server with a normalized url/origin if not found.
*/
public RemoteServer findRemoteServer(String origin) {
return servers.stream().filter(server -> server.origin.equalsIgnoreCase(origin))
String strippedOrigin = stripProtocol(origin);
return servers.stream().filter(server -> server.origin.equalsIgnoreCase(strippedOrigin))
.findFirst()
.orElseGet(() -> {
URI normalizedUri = normalize(origin);
URI normalizedUri = normalize(strippedOrigin);
String normalizedOrigin = normalizedUri.getHost() + maybePort(normalizedUri.getPort(), normalizedUri.getScheme());
return new RemoteServer(Service.Unknown, normalizedOrigin, normalizedUri);
});
Expand Down Expand Up @@ -281,6 +301,10 @@ private String repositoryPath(RemoteServerMatch match, URI normalizedUri) {

private static final Pattern PORT_PATTERN = Pattern.compile(":\\d+(/.+)(/.+)+");

static URI normalize(URI url) {
return normalize(url.toString());
}

static URI normalize(String url) {
try {
URIish uri = new URIish(url);
Expand Down Expand Up @@ -374,10 +398,11 @@ public Set<String> allOrigins() {
Set<String> origins = new LinkedHashSet<>();
origins.add(origin);
for (URI uri : uris) {
URI normalized = Parser.normalize(uri.toString());
URI normalized = Parser.normalize(uri);
origins.add(Parser.stripProtocol(normalized.toString()));
}
return origins;
}

}
}
60 changes: 60 additions & 0 deletions rewrite-core/src/main/java/org/openrewrite/semver/LatestMinor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2021 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.semver;

import lombok.Value;
import org.jspecify.annotations.Nullable;
import org.openrewrite.Validated;

@Value
public class LatestMinor implements VersionComparator {
@Nullable
String metadataPattern;

@Override
public boolean isValid(@Nullable String currentVersion, String version) {
Validated<? extends VersionComparator> validated = currentVersion == null ?
LatestRelease.buildLatestRelease("latest.release", metadataPattern) :
TildeRange.build("~" + Semver.majorVersion(currentVersion), metadataPattern);

if (validated.isValid()) {
VersionComparator comparator = validated.getValue();
if (comparator != null) {
return comparator.isValid(currentVersion, version);
}
}
return false;
}

@Override
public int compare(@Nullable String currentVersion, String v1, String v2) {
if(currentVersion == null) {
return new LatestRelease(null)
.compare(null, v1, v2);
}

//noinspection ConstantConditions
return TildeRange.build("~" + Semver.majorVersion(currentVersion) + "." + Semver.minorVersion(currentVersion), metadataPattern)
.getValue()
.compare(currentVersion, v1, v2);
}

public static Validated<LatestMinor> build(String toVersion, @Nullable String metadataPattern) {
return "latest.minor".equalsIgnoreCase(toVersion) ?
Validated.valid("latestMinor", new LatestMinor(metadataPattern)) :
Validated.invalid("latestMinor", toVersion, "not latest release");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public int compare(@Nullable String currentVersion, String v1, String v2) {
}

public static Validated<LatestRelease> buildLatestRelease(String toVersion, @Nullable String metadataPattern) {
return "latest.release".equalsIgnoreCase(toVersion) ?
return "latest.release".equalsIgnoreCase(toVersion) || "latest.major".equalsIgnoreCase(toVersion) ?
Validated.valid("latestRelease", new LatestRelease(metadataPattern)) :
Validated.invalid("latestRelease", toVersion, "not latest release");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public static Validated<VersionComparator> validate(String toVersion, @Nullable
).and(Validated.<VersionComparator>none()
.or(LatestRelease.buildLatestRelease(toVersion, metadataPattern))
.or(LatestIntegration.build(toVersion, metadataPattern))
.or(LatestMinor.build(toVersion, metadataPattern))
.or(LatestPatch.build(toVersion, metadataPattern))
.or(HyphenRange.build(toVersion, metadataPattern))
.or(XRange.build(toVersion, metadataPattern))
Expand Down
40 changes: 32 additions & 8 deletions rewrite-core/src/main/java/org/openrewrite/text/Find.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,51 @@ public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
if (!matcher.find()) {
return sourceFile;
}
matcher.reset();

String sourceFilePath = sourceFile.getSourcePath().toString();

List<PlainText.Snippet> snippets = new ArrayList<>();
int previousEnd = 0;
while (matcher.find()) {

int lastNewLineIndex = -1;
int nextNewLineIndex = -1;
boolean isFirstMatch = true;

do {
int matchStart = matcher.start();
snippets.add(snippet(rawText.substring(previousEnd, matchStart)));
snippets.add(SearchResult.found(snippet(rawText.substring(matchStart, matcher.end()))));
previousEnd = matcher.end();

int startLine = Math.max(0, rawText.substring(0, matchStart).lastIndexOf('\n') + 1);
// For the first match, search backwards
if (isFirstMatch) {
lastNewLineIndex = rawText.lastIndexOf('\n', matchStart);
nextNewLineIndex = rawText.indexOf('\n', lastNewLineIndex + 1);
isFirstMatch = false;
} else if (nextNewLineIndex != -1 && nextNewLineIndex < matchStart) {
// Advance lastNewLineIndex while before match start
while (nextNewLineIndex != -1 && nextNewLineIndex < matchStart) {
lastNewLineIndex = nextNewLineIndex;
nextNewLineIndex = rawText.indexOf('\n', lastNewLineIndex + 1);
}
}

int startLine = lastNewLineIndex + 1;
int endLine = rawText.indexOf('\n', matcher.end());
if (endLine == -1) {
endLine = rawText.length();
}

//noinspection StringBufferReplaceableByString
textMatches.insertRow(ctx, new TextMatches.Row(
sourceFile.getSourcePath().toString(),
rawText.substring(startLine, matcher.start()) + "~~>" +
rawText.substring(matcher.start(), endLine)
sourceFilePath,
new StringBuilder(endLine - startLine + 3)
.append(rawText, startLine, matchStart)
.append("~~>")
.append(rawText, matchStart, endLine)
.toString()
));
}
} while (matcher.find());
snippets.add(snippet(rawText.substring(previousEnd)));
return plainText.withText("").withSnippets(snippets);
}
Expand All @@ -160,8 +184,8 @@ public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
return visitor;
}


private static PlainText.Snippet snippet(String text) {
return new PlainText.Snippet(Tree.randomId(), Markers.EMPTY, text);
}

}
Loading

0 comments on commit 69803b8

Please sign in to comment.