Skip to content

Commit

Permalink
Record parse failures into the execution context as Quarks with a Marker
Browse files Browse the repository at this point in the history
  • Loading branch information
sambsnyd committed Sep 22, 2022
1 parent 947b436 commit d296838
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2022 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;

import lombok.Getter;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.marker.SearchResult;

import java.util.UUID;

public class ParseExceptionResult extends SearchResult {

@Getter
private final Throwable throwable;

public ParseExceptionResult(Throwable t) {
this(Tree.randomId(), t);
}

public ParseExceptionResult(UUID id, Throwable t) {
super(id, t.toString());
throwable = t;
}
}
25 changes: 15 additions & 10 deletions rewrite-core/src/main/java/org/openrewrite/binary/BinaryParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.openrewrite.Parser;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.marker.Markers;
import org.openrewrite.tree.ParsingExecutionContextView;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand All @@ -36,18 +37,22 @@
public class BinaryParser implements Parser<Binary> {
@Override
public List<Binary> parseInputs(Iterable<Input> sources, @Nullable Path relativeTo, ExecutionContext ctx) {
List<Binary> plainTexts = new ArrayList<>();
List<Binary> binaries = new ArrayList<>();
for (Input source : sources) {
plainTexts.add(new Binary(randomId(),
relativeTo == null ?
source.getPath() :
relativeTo.relativize(source.getPath()).normalize(),
Markers.EMPTY,
source.getFileAttributes(),
null,
readAllBytes(source.getSource(ctx))));
Path path = source.getRelativePath(relativeTo);
try {
binaries.add(new Binary(randomId(),
path,
Markers.EMPTY,
source.getFileAttributes(),
null,
readAllBytes(source.getSource())));
} catch (Exception e) {
ParsingExecutionContextView.view(ctx).parseFailure(path, e);
ctx.getOnError().accept(e);
}
}
return plainTexts;
return binaries;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ public List<Quark> parseInputs(Iterable<Parser.Input> sources, @Nullable Path re
List<Quark> quarks = new ArrayList<>();
for (Parser.Input source : sources) {
quarks.add(new Quark(randomId(),
relativeTo == null ?
source.getPath() :
relativeTo.relativize(source.getPath()).normalize(),
source.getRelativePath(relativeTo),
Markers.EMPTY,
null,
source.getFileAttributes()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,23 @@ public List<PlainText> parseInputs(Iterable<Input> sources, @Nullable Path relat
List<PlainText> plainTexts = new ArrayList<>();
ParsingEventListener parsingListener = ParsingExecutionContextView.view(ctx).getParsingListener();
for (Input source : sources) {
EncodingDetectingInputStream is = source.getSource(ctx);
String sourceText = is.readFully();
PlainText plainText = new PlainText(randomId(),
relativeTo == null ?
source.getPath() :
relativeTo.relativize(source.getPath()).normalize(),
Markers.EMPTY,
is.getCharset().name(),
is.isCharsetBomMarked(),
source.getFileAttributes(),
null,
sourceText);
plainTexts.add(plainText);
parsingListener.parsed(source, plainText);
Path path = source.getRelativePath(relativeTo);
try {
EncodingDetectingInputStream is = source.getSource(ctx);
PlainText plainText = new PlainText(randomId(),
path,
Markers.EMPTY,
is.getCharset().name(),
is.isCharsetBomMarked(),
source.getFileAttributes(),
null,
is.readFully());
plainTexts.add(plainText);
parsingListener.parsed(source, plainText);
} catch (Throwable t) {
ParsingExecutionContextView.view(ctx).parseFailure(path, t);
ctx.getOnError().accept(t);
}
}
return plainTexts;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,26 @@

import org.openrewrite.DelegatingExecutionContext;
import org.openrewrite.ExecutionContext;
import org.openrewrite.ParseExceptionResult;
import org.openrewrite.Tree;
import org.openrewrite.marker.Markers;
import org.openrewrite.quark.Quark;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.openrewrite.internal.lang.Nullable;

import java.nio.charset.Charset;

public class ParsingExecutionContextView extends DelegatingExecutionContext {
private static final String PARSING_LISTENER = "org.openrewrite.core.parsingListener";

private static final String CHARSET = "org.openrewrite.parser.charset";

private static final String PARSING_FAILURES = "org.openrewrite.core.parsingFailures";

public ParsingExecutionContextView(ExecutionContext delegate) {
super(delegate);
}
Expand All @@ -45,6 +57,27 @@ public ParsingEventListener getParsingListener() {
return getMessage(PARSING_LISTENER, ParsingEventListener.NOOP);
}

@SuppressWarnings("UnusedReturnValue")
public ParsingExecutionContextView parseFailure(Path path, Throwable t) {
if(path.isAbsolute()) {
throw new RuntimeException("Relative paths only");
}
putMessageInCollection(PARSING_FAILURES,
new Quark(Tree.randomId(), path, Markers.EMPTY.addIfAbsent(new ParseExceptionResult(t)), null, null),
ArrayList::new);
return this;
}

@SuppressWarnings("unused")
public List<Quark> getParseFailures() {
return getMessage(PARSING_FAILURES, Collections.emptyList());
}

@SuppressWarnings("unused")
public List<Quark> pollParseFailures() {
return pollMessage(PARSING_FAILURES, Collections.emptyList());
}

public ParsingExecutionContextView setCharset(@Nullable Charset charset) {
putMessage(CHARSET, charset);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ public List<G.CompilationUnit> parse(@Language("groovy") String... sources) {

@Override
public List<G.CompilationUnit> parseInputs(Iterable<Input> sources, @Nullable Path relativeTo, ExecutionContext ctx) {
ParsingEventListener parsingListener = ParsingExecutionContextView.view(ctx).getParsingListener();
List<CompiledGroovySource> compilerCus = parseInputsToCompilerAst(sources, relativeTo, ctx);
ParsingExecutionContextView pctx = ParsingExecutionContextView.view(ctx);
ParsingEventListener parsingListener = pctx.getParsingListener();
List<CompiledGroovySource> compilerCus = parseInputsToCompilerAst(sources, relativeTo, pctx);
List<G.CompilationUnit> cus = new ArrayList<>(compilerCus.size());

for (CompiledGroovySource compiled : compilerCus) {
Expand All @@ -111,14 +112,15 @@ public List<G.CompilationUnit> parseInputs(Iterable<Input> sources, @Nullable Pa
cus.add(gcu);
parsingListener.parsed(compiled.getInput(), gcu);
} catch (Throwable t) {
pctx.parseFailure(compiled.getInput().getRelativePath(relativeTo), t);
ctx.getOnError().accept(t);
}
}

return cus;
}

List<CompiledGroovySource> parseInputsToCompilerAst(Iterable<Input> sources, @Nullable Path relativeTo, ExecutionContext ctx) {
List<CompiledGroovySource> parseInputsToCompilerAst(Iterable<Input> sources, @Nullable Path relativeTo, ParsingExecutionContextView ctx) {
List<CompiledGroovySource> cus = new ArrayList<>();

for (Input input : sources) {
Expand Down Expand Up @@ -162,6 +164,7 @@ List<CompiledGroovySource> parseInputsToCompilerAst(Iterable<Input> sources, @Nu

cus.add(new CompiledGroovySource(input, unit, ast));
} catch (Throwable t) {
ctx.parseFailure(input.getRelativePath(relativeTo), t);
ctx.getOnError().accept(t);
} finally {
if (logCompilationWarningsAndErrors && (errorCollector.hasErrors() || errorCollector.hasWarnings())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,28 @@
import org.openrewrite.Parser;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.java.JavaTypeSignatureBuilderTest;
import org.openrewrite.tree.ParsingExecutionContextView;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.Objects;

import static java.util.Collections.singletonList;

public class GroovyTypeSignatureBuilderTest implements JavaTypeSignatureBuilderTest {

private static final String goat = StringUtils.readFully(
GroovyTypeSignatureBuilderTest.class.getResourceAsStream("/GroovyTypeGoat.groovy"));
Objects.requireNonNull(GroovyTypeSignatureBuilderTest.class.getResourceAsStream("/GroovyTypeGoat.groovy")));

private static final CompiledGroovySource cu = GroovyParser.builder()
.logCompilationWarningsAndErrors(true)
.build()
.parseInputsToCompilerAst(
singletonList(new Parser.Input(Paths.get("GroovyTypeGoat.groovy"), () -> new ByteArrayInputStream(goat.getBytes(StandardCharsets.UTF_8)))),
null,
new InMemoryExecutionContext(Throwable::printStackTrace))
new ParsingExecutionContextView(new InMemoryExecutionContext(Throwable::printStackTrace)))
.iterator()
.next();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public List<Hcl.ConfigFile> parseInputs(Iterable<Input> sourceFiles, @Nullable P
return configFile;
} catch (Throwable t) {
sample.stop(MetricsHelper.errorTags(timer, t).register(Metrics.globalRegistry));
ParsingExecutionContextView.view(ctx).parseFailure(sourceFile.getRelativePath(relativeTo), t);
ctx.getOnError().accept(t);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public List<J.CompilationUnit> parseInputs(Iterable<Input> sourceFiles, @Nullabl
.tag("file.type", "Java")
.tag("step", "(3) Map to Rewrite AST"), t)
.register(Metrics.globalRegistry));

ParsingExecutionContextView.view(ctx).parseFailure(input.getRelativePath(relativeTo), t);
ctx.getOnError().accept(t);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public List<J.CompilationUnit> parseInputs(Iterable<Input> sourceFiles, @Nullabl
.tag("file.type", "Java")
.tag("step", "(3) Map to Rewrite AST"), t)
.register(Metrics.globalRegistry));

ParsingExecutionContextView.view(ctx).parseFailure(input.getRelativePath(relativeTo), t);
ctx.getOnError().accept(t);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public List<Json.Document> parseInputs(Iterable<Input> sourceFiles, @Nullable Pa
return document;
} catch (Throwable t) {
sample.stop(MetricsHelper.errorTags(timer, t).register(Metrics.globalRegistry));
ParsingExecutionContextView.view(ctx).parseFailure(sourceFile.getRelativePath(relativeTo), t);
ctx.getOnError().accept(new IllegalStateException(sourceFile.getPath() + " " + t.getMessage(), t));
return null;
}
Expand Down
36 changes: 20 additions & 16 deletions rewrite-maven/src/main/java/org/openrewrite/maven/MavenParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.openrewrite.maven.tree.Parent;
import org.openrewrite.maven.tree.Pom;
import org.openrewrite.maven.tree.ResolvedPom;
import org.openrewrite.tree.ParsingExecutionContextView;
import org.openrewrite.xml.XmlParser;
import org.openrewrite.xml.tree.Xml;

Expand Down Expand Up @@ -81,25 +82,28 @@ public List<Xml.Document> parseInputs(Iterable<Input> sources, @Nullable Path re
Map<Xml.Document, Pom> projectPoms = new LinkedHashMap<>();
Map<Path, Pom> projectPomsByPath = new HashMap<>();
for (Input source : sources) {
Path pomPath = (relativeTo == null) ?
source.getPath() :
relativeTo.relativize(source.getPath());
Pom pom = RawPom.parse(source.getSource(ctx), null)
.toPom(pomPath, null);
if (relativeTo != null) {
if (pom.getProperties() == null || pom.getProperties().isEmpty()) {
pom = pom.withProperties(new LinkedHashMap<>());
Path pomPath = source.getRelativePath(relativeTo);
try {
Pom pom = RawPom.parse(source.getSource(ctx), null)
.toPom(pomPath, null);
if (relativeTo != null) {
if (pom.getProperties() == null || pom.getProperties().isEmpty()) {
pom = pom.withProperties(new LinkedHashMap<>());
}
pom.getProperties().put("project.basedir", relativeTo.toString());
pom.getProperties().put("basedir", relativeTo.toString());
}
pom.getProperties().put("project.basedir", relativeTo.toString());
pom.getProperties().put("basedir", relativeTo.toString());
}

Xml.Document xml = new MavenXmlParser()
.parseInputs(singletonList(source), relativeTo, ctx)
.iterator().next();
Xml.Document xml = new MavenXmlParser()
.parseInputs(singletonList(source), relativeTo, ctx)
.iterator().next();

projectPoms.put(xml, pom);
projectPomsByPath.put(pomPath, pom);
projectPoms.put(xml, pom);
projectPomsByPath.put(pomPath, pom);
} catch (Throwable t) {
ParsingExecutionContextView.view(ctx).parseFailure(pomPath, t);
ctx.getOnError().accept(t);
}
}

List<Xml.Document> parsed = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,21 @@ public List<Properties.File> parseInputs(Iterable<Input> sourceFiles, @Nullable
ParsingEventListener parsingListener = ParsingExecutionContextView.view(ctx).getParsingListener();
return acceptedInputs(sourceFiles).stream()
.map(sourceFile -> {
Path path = sourceFile.getRelativePath(relativeTo);
Timer.Builder timer = Timer.builder("rewrite.parse")
.description("The time spent parsing a properties file")
.tag("file.type", "Properties");
Timer.Sample sample = Timer.start();
try (EncodingDetectingInputStream is = sourceFile.getSource(ctx)) {
Properties.File file = parseFromInput(sourceFile.getRelativePath(relativeTo), is)
Properties.File file = parseFromInput(path, is)
.withFileAttributes(sourceFile.getFileAttributes());
sample.stop(MetricsHelper.successTags(timer).register(Metrics.globalRegistry));
parsingListener.parsed(sourceFile, file);
return file;
} catch (Throwable t) {
sample.stop(MetricsHelper.errorTags(timer, t).register(Metrics.globalRegistry));
ctx.getOnError().accept(new IllegalStateException(sourceFile.getPath() + " " + t.getMessage(), t));
ParsingExecutionContextView.view(ctx).parseFailure(path, t);
return null;
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public List<Proto.Document> parseInputs(Iterable<Input> sourceFiles, @Nullable P
.description("The time spent parsing a Protobuf file")
.tag("file.type", "Proto");
Timer.Sample sample = Timer.start();
Path path = sourceFile.getRelativePath(relativeTo);
try {
EncodingDetectingInputStream is = sourceFile.getSource(ctx);
String sourceStr = is.readFully();
Expand All @@ -62,7 +63,7 @@ public List<Proto.Document> parseInputs(Iterable<Input> sourceFiles, @Nullable P
}

Proto.Document document = new ProtoParserVisitor(
sourceFile.getRelativePath(relativeTo),
path,
sourceFile.getFileAttributes(),
sourceStr,
is.getCharset(),
Expand All @@ -73,7 +74,8 @@ public List<Proto.Document> parseInputs(Iterable<Input> sourceFiles, @Nullable P
return document;
} catch (Throwable t) {
sample.stop(MetricsHelper.errorTags(timer, t).register(Metrics.globalRegistry));
ctx.getOnError().accept(new IllegalStateException(sourceFile.getPath() + " " + t.getMessage(), t));
ctx.getOnError().accept(new IllegalStateException(path + " " + t.getMessage(), t));
ParsingExecutionContextView.view(ctx).parseFailure(path, t);
return null;
}
})
Expand Down
Loading

0 comments on commit d296838

Please sign in to comment.