All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.javascript.JavaScriptParser Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2023 the original author or authors.
 * 

* 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 *

* https://www.apache.org/licenses/LICENSE-2.0 *

* 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.javascript; import lombok.Value; import org.jspecify.annotations.Nullable; import org.openrewrite.ExecutionContext; import org.openrewrite.InMemoryExecutionContext; import org.openrewrite.Parser; import org.openrewrite.SourceFile; import org.openrewrite.internal.EncodingDetectingInputStream; import org.openrewrite.java.internal.JavaTypeCache; import org.openrewrite.javascript.internal.JavetNativeBridge; import org.openrewrite.javascript.internal.TypeScriptParserVisitor; import org.openrewrite.javascript.internal.tsc.TSCRuntime; import org.openrewrite.javascript.tree.JS; import org.openrewrite.style.NamedStyles; import org.openrewrite.tree.ParseError; import org.openrewrite.tree.ParsingEventListener; import org.openrewrite.tree.ParsingExecutionContextView; import java.io.ByteArrayInputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.stream.Stream; public class JavaScriptParser implements Parser { @Nullable private static TSCRuntime RUNTIME; private static TSCRuntime runtime() { if (RUNTIME == null) { JavetNativeBridge.init(); RUNTIME = TSCRuntime.init(); Runtime.getRuntime().addShutdownHook(new Thread(() -> RUNTIME.close())); } return RUNTIME; } @Value private static class SourceWrapper { Parser.Input input; Path sourcePath; Charset charset; boolean isCharsetBomMarked; String sourceText; } private final Collection styles; private JavaScriptParser(Collection styles) { this.styles = styles; } @Override public Stream parse(String... sources) { List inputs = new ArrayList<>(sources.length); for (int i = 0; i < sources.length; i++) { Path path = Paths.get("f" + i + ".ts"); int j = i; inputs.add(new Input( path, null, () -> new ByteArrayInputStream(sources[j].getBytes(StandardCharsets.UTF_8)), true )); } return parseInputs( inputs, null, new InMemoryExecutionContext() ); } @Override public Stream parseInputs(Iterable sources, @Nullable Path relativeTo, ExecutionContext ctx) { ParsingExecutionContextView pctx = ParsingExecutionContextView.view(ctx); Map sourcesByRelativePath = new LinkedHashMap<>(); for (Input input : sources) { EncodingDetectingInputStream is = input.getSource(pctx); String inputSourceText = is.readFully(); Path relativePath = input.getRelativePath(relativeTo); SourceWrapper source = new SourceWrapper( input, relativePath, is.getCharset(), is.isCharsetBomMarked(), inputSourceText ); sourcesByRelativePath.put(relativePath, source); } List compilationUnits = new ArrayList<>(sourcesByRelativePath.size()); ParsingEventListener parsingListener = ParsingExecutionContextView.view(pctx).getParsingListener(); Map sourceTextsForTSC = new LinkedHashMap<>(); sourcesByRelativePath.forEach((relativePath, sourceText) -> sourceTextsForTSC.put(relativePath, sourceText.sourceText)); try { //noinspection resource runtime().parseSourceTexts( sourceTextsForTSC, (node, context) -> { SourceWrapper source = sourcesByRelativePath.get(context.getRelativeSourcePath()); parsingListener.startedParsing(source.getInput()); TypeScriptParserVisitor fileMapper = new TypeScriptParserVisitor( node, context, source.getSourcePath(), new JavaTypeCache(), source.getCharset().toString(), source.isCharsetBomMarked(), styles ); SourceFile cu; try { cu = fileMapper.visitSourceFile(); parsingListener.parsed(source.getInput(), cu); } catch (Throwable t) { ((ExecutionContext) pctx).getOnError().accept(t); cu = ParseError.build(JavaScriptParser.builder().build(), source.getInput(), relativeTo, pctx, t); } compilationUnits.add(cu); } ); } catch (Exception e) { return acceptedInputs(sources).map(input -> ParseError.build(this, input, relativeTo, ctx, e)); } return compilationUnits.stream(); } private final static List EXTENSIONS = Collections.unmodifiableList(Arrays.asList( ".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".mts", ".cts" )); // Exclude Yarn's Plug'n'Play loader files (https://yarnpkg.com/features/pnp) private final static List EXCLUSIONS = Collections.unmodifiableList(Arrays.asList( ".pnp.cjs", ".pnp.loader.mjs" )); @Override public boolean accept(Path path) { if (path.toString().contains("/dist/")) { // FIXME this is a workaround to not having tsconfig info return false; } final String filename = path.getFileName().toString().toLowerCase(); for (String ext : EXTENSIONS) { if (filename.endsWith(ext) && !EXCLUSIONS.contains(filename)) { return true; } } return false; } @Override public Path sourcePathFromSourceText(Path prefix, String sourceCode) { return prefix.resolve("file.ts"); } public static Builder builder() { return new Builder(); } public static class Builder extends Parser.Builder { // FIXME add logCompilationWarningsAndErrors. Collection styles = new ArrayList<>(); public Builder() { super(JS.CompilationUnit.class); } public Builder styles(Iterable styles) { for (NamedStyles style : styles) { this.styles.add(style); } return this; } @Override public JavaScriptParser build() { return new JavaScriptParser(styles); } @Override public String getDslName() { return "javascript"; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy