Skip to content

Commit

Permalink
Merge branch 'main' into yaml-tags
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-at-moderne authored Jan 30, 2025
2 parents f548be8 + d33ff3f commit 7e808f5
Show file tree
Hide file tree
Showing 197 changed files with 12,523 additions and 1,065 deletions.
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionSha256Sum=7a00d51fb93147819aab76024feece20b6b84e420694101f276be952e08bef03
distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.openrewrite;

import org.jspecify.annotations.Nullable;
import org.openrewrite.scheduling.WorkingDirectoryExecutionContextView;

public class CursorValidatingExecutionContextView extends DelegatingExecutionContext {
private static final String VALIDATE_CURSOR_ACYCLIC = "org.openrewrite.CursorValidatingExecutionContextView.ValidateCursorAcyclic";
Expand Down Expand Up @@ -49,15 +50,20 @@ public CursorValidatingExecutionContextView setValidateImmutableExecutionContext

@Override
public void putMessage(String key, @Nullable Object value) {
boolean mutationAllowed = !getMessage(VALIDATE_CTX_MUTATION, false) || key.equals(VALIDATE_CURSOR_ACYCLIC) || key.equals(VALIDATE_CTX_MUTATION)
|| key.equals(ExecutionContext.CURRENT_CYCLE) || key.equals(ExecutionContext.CURRENT_RECIPE) || key.equals(ExecutionContext.DATA_TABLES)
|| key.startsWith("org.openrewrite.maven"); // MavenExecutionContextView stores metrics
assert mutationAllowed
: "Recipe mutated execution context key \"" + key + "\". " +
"Recipes should not mutate the contents of the ExecutionContext as it allows mutable state to leak between " +
"recipes, opening the door for difficult to debug recipe composition errors. " +
"If you need to store state within the execution of a single recipe use Cursor messaging. " +
"If you want to pass state between recipes, use a ScanningRecipe instead.";
boolean mutationAllowed = !getMessage(VALIDATE_CTX_MUTATION, false)
|| key.equals(VALIDATE_CURSOR_ACYCLIC)
|| key.equals(VALIDATE_CTX_MUTATION)
|| key.equals(ExecutionContext.CURRENT_CYCLE)
|| key.equals(ExecutionContext.CURRENT_RECIPE)
|| key.equals(ExecutionContext.DATA_TABLES)
|| key.equals(WorkingDirectoryExecutionContextView.WORKING_DIRECTORY_ROOT)
|| key.startsWith("org.openrewrite.maven") // MavenExecutionContextView stores metrics
|| key.startsWith("io.moderne"); // We ought to know what we're doing
assert mutationAllowed : "Recipe mutated execution context key \"" + key + "\". " +
"Recipes should not mutate the contents of the ExecutionContext as it allows mutable state to leak between " +
"recipes, opening the door for difficult to debug recipe composition errors. " +
"If you need to store state within the execution of a single recipe use Cursor messaging. " +
"If you want to pass state between recipes, use a ScanningRecipe instead.";
super.putMessage(key, value);
}
}
19 changes: 13 additions & 6 deletions rewrite-core/src/main/java/org/openrewrite/SourceFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@

import org.jspecify.annotations.Nullable;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.style.NamedStyles;
import org.openrewrite.style.Style;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;

public interface SourceFile extends Tree {

Expand Down Expand Up @@ -70,13 +70,20 @@ default boolean printEqualsInput(Parser.Input input, ExecutionContext ctx) {

<T extends SourceFile> T withFileAttributes(@Nullable FileAttributes fileAttributes);

default <S extends Style> @Nullable S getStyle(Class<S> style) {
return NamedStyles.merge(style, getMarkers().findAll(NamedStyles.class));
/**
* @deprecated Use {@link org.openrewrite.style.Style#from(Class, SourceFile)} instead.
*/
@Deprecated
default <S extends Style> @Nullable S getStyle(Class<S> styleClass) {
return Style.from(styleClass, this);
}

default <S extends Style> S getStyle(Class<S> style, S defaultStyle) {
S s = getStyle(style);
return s == null ? defaultStyle : s;
/**
* @deprecated Use {@link org.openrewrite.style.Style#from(Class, SourceFile, Supplier)} instead.
*/
@Deprecated
default <S extends Style> S getStyle(Class<S> styleClass, S defaultStyle) {
return Style.from(styleClass, this, () -> defaultStyle);
}

default <P> byte[] printAllAsBytes(P p) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@


import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.With;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import lombok.experimental.NonFinal;
import org.jspecify.annotations.Nullable;
import org.openrewrite.GitRemote;
Expand All @@ -44,6 +42,8 @@
import java.util.*;

import static java.util.Collections.emptyList;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static org.openrewrite.Tree.randomId;

@Value
Expand Down Expand Up @@ -187,7 +187,7 @@ public GitProvenance(UUID id,
*/
public static @Nullable GitProvenance fromProjectDirectory(Path projectDir,
@Nullable BuildEnvironment environment,
GitRemote.@Nullable Parser gitRemoteParser) {
GitRemote.@Nullable Parser gitRemoteParser) {
if (gitRemoteParser == null) {
gitRemoteParser = new GitRemote.Parser();
}
Expand Down Expand Up @@ -371,16 +371,22 @@ private static List<Committer> getCommitters(Repository repository) {
head = headRef.getObjectId();
}

Map<String, Committer> committers = new TreeMap<>();
Map<String, String> committerName = new HashMap<>();
Map<String, NavigableMap<LocalDate, Integer>> commitMap = new HashMap<>();
for (RevCommit commit : git.log().add(head).call()) {
PersonIdent who = commit.getAuthorIdent();
Committer committer = committers.computeIfAbsent(who.getEmailAddress(),
email -> new Committer(who.getName(), email, new TreeMap<>()));
committer.getCommitsByDay().compute(who.getWhen().toInstant().atZone(who.getTimeZone().toZoneId())
committerName.putIfAbsent(who.getEmailAddress(), who.getName());
commitMap.computeIfAbsent(who.getEmailAddress(),
email -> new TreeMap<>()).compute(who.getWhen().toInstant().atZone(who.getTimeZone().toZoneId())
.toLocalDate(),
(day, count) -> count == null ? 1 : count + 1);
}
return new ArrayList<>(committers.values());
return committerName.entrySet().stream()
.map(c -> new Committer(
c.getValue(),
c.getKey(),
commitMap.get(c.getKey()))
).collect(toList());
} catch (IOException | GitAPIException e) {
return emptyList();
}
Expand Down Expand Up @@ -419,10 +425,47 @@ public enum EOL {
}

@Value
@With
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public static class Committer {

@With
String name;

@With
String email;
NavigableMap<LocalDate, Integer> commitsByDay;

@Getter(AccessLevel.PRIVATE)
int[] data;

@JsonCreator
static Committer from(
@JsonProperty("name") String name, @JsonProperty("email") String email,
@JsonProperty("dates") int @Nullable [] data,
@Nullable @JsonProperty("commitsByDay") NavigableMap<LocalDate, Integer> commitsByDay) {
if (commitsByDay != null) {
return new Committer(name, email, commitsByDay);
} else {
return new Committer(name, email, requireNonNull(data));
}
}

public Committer(String name, String email, NavigableMap<LocalDate, Integer> commitsByDay) {
this.name = name;
this.email = email;
this.data = new int[commitsByDay.size() * 2];
int i = 0;
for (Map.Entry<LocalDate, Integer> entry : commitsByDay.entrySet()) {
data[i++] = (int) entry.getKey().toEpochDay();
data[i++] = entry.getValue();
}
}

public NavigableMap<LocalDate, Integer> getCommitsByDay() {
TreeMap<LocalDate, Integer> commitsByDay = new TreeMap<>();
for (int i = 0; i < data.length; ) {
commitsByDay.put(LocalDate.ofEpochDay(data[i++]), data[i++]);
}
return commitsByDay;
}
}
}
31 changes: 12 additions & 19 deletions rewrite-core/src/main/java/org/openrewrite/remote/Remote.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@
* If a Checksum is provided it will be used to validate the integrity of the downloaded file.
*/
public interface Remote extends SourceFile {
URI getUri();

<R extends Remote> R withUri(URI uri);

/**
* Any text describing what this remote URI represents. Used to present human-readable results to an end user.
*/
Expand All @@ -66,7 +62,6 @@ default <T extends SourceFile> T withChecksum(@Nullable Checksum checksum) {
return (T) this;
}


/**
* Download the remote file
*
Expand Down Expand Up @@ -97,16 +92,12 @@ default <P> boolean isAcceptable(TreeVisitor<?, P> v, P p) {
return v.isAdaptableTo(RemoteVisitor.class);
}

static Builder builder(SourceFile before, URI uri) {
return new Builder(before.getId(), before.getSourcePath(), before.getMarkers(), uri);
static Builder builder(SourceFile before) {
return new Builder(before.getId(), before.getSourcePath(), before.getMarkers());
}

static Builder builder(Path sourcePath, URI uri) {
return new Builder(Tree.randomId(), sourcePath, Markers.EMPTY, uri);
}

static Builder builder(UUID id, Path sourcePath, Markers markers, URI uri) {
return new Builder(id, sourcePath, markers, uri);
static Builder builder(Path sourcePath) {
return new Builder(Tree.randomId(), sourcePath, Markers.EMPTY);
}

@Override
Expand All @@ -127,7 +118,6 @@ class Builder {
protected final UUID id;
protected final Path sourcePath;
protected final Markers markers;
protected final URI uri;

@Nullable
@Language("markdown")
Expand All @@ -144,11 +134,10 @@ class Builder {
@Nullable
FileAttributes fileAttributes;

Builder(UUID id, Path sourcePath, Markers markers, URI uri) {
Builder(UUID id, Path sourcePath, Markers markers) {
this.id = id;
this.sourcePath = sourcePath;
this.markers = markers;
this.uri = uri;
}

public Builder description(@Language("markdown") String description) {
Expand Down Expand Up @@ -176,17 +165,21 @@ public Builder checksum(Checksum checksum) {
return this;
}

public RemoteFile build() {
public RemoteResource build(InputStream inputStream) {
return new RemoteResource(id, sourcePath, markers, inputStream, charset, charsetBomMarked, fileAttributes, description, checksum);
}

public RemoteFile build(URI uri) {
return new RemoteFile(id, sourcePath, markers, uri, charset, charsetBomMarked, fileAttributes, description, checksum);
}

public RemoteArchive build(Path path) {
public RemoteArchive build(URI uri, Path path) {
return new RemoteArchive(id, sourcePath, markers, uri, charset, charsetBomMarked, fileAttributes, description,
Arrays.asList(path.toString().replace("/", "\\/").replace(".", "\\.")
.split("!")), checksum);
}

public RemoteArchive build(String... paths) {
public RemoteArchive build(URI uri, String... paths) {
return new RemoteArchive(id, sourcePath, markers, uri, charset, charsetBomMarked, fileAttributes, description,
Arrays.asList(paths), checksum);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
* Useful when a Recipe wishes to create a SourceFile based on something specific from within a remote archive, but not
* the entire archive.
* <p>
* Downloading and extracting the correct file from within the archive are not handled during Recipe execution.
* Post-processing of Recipe results by a build plugin or other caller of OpenRewrite is responsible for this.
* Downloading and extracting the correct file from within the archive are not handled during recipe execution.
* Post-processing of recipe results by a build plugin or other caller of OpenRewrite is responsible for this.
*/
@Value
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
Expand All @@ -70,6 +70,7 @@ public class RemoteArchive implements Remote {
FileAttributes fileAttributes;

@Language("markdown")
@Nullable
String description;

/**
Expand All @@ -92,10 +93,10 @@ public InputStream getInputStream(ExecutionContext ctx) {
RemoteArtifactCache cache = RemoteExecutionContextView.view(ctx).getArtifactCache();
try {
Path localArchive = cache.compute(uri, () -> {
//noinspection resource
if ("file".equals(uri.getScheme())) {
return Files.newInputStream(Paths.get(uri));
}
//noinspection resource
HttpSender.Response response = httpSender.send(httpSender.get(uri.toString()).build());
if (response.isSuccessful()) {
return response.getBody();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class RemoteFile implements Remote {
FileAttributes fileAttributes;

@Language("markdown")
@Nullable
String description;

@Nullable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2025 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.remote;

import lombok.EqualsAndHashCode;
import lombok.Value;
import lombok.With;
import org.intellij.lang.annotations.Language;
import org.jspecify.annotations.Nullable;
import org.openrewrite.Checksum;
import org.openrewrite.ExecutionContext;
import org.openrewrite.FileAttributes;
import org.openrewrite.marker.Markers;

import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.UUID;

/**
* A remote resource that can be fetched from an {@link java.io.InputStream} which
* could be, for example, a classpath resource.
*/
@Value
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
@With
public class RemoteResource implements Remote {
@EqualsAndHashCode.Include
UUID id;

Path sourcePath;
Markers markers;
InputStream inputStream;

@Nullable
Charset charset;

boolean charsetBomMarked;

@Nullable
FileAttributes fileAttributes;

@Language("markdown")
@Nullable
String description;

@Nullable
Checksum checksum;

/**
* Note that this method can only be called once, consuming the
* {@link InputStream} in the process.
*
* @param ctx Unused in this implementation of {@link Remote}.
* @return The data of the file.
*/
@Override
public InputStream getInputStream(ExecutionContext ctx) {
return inputStream;
}
}
Loading

0 comments on commit 7e808f5

Please sign in to comment.