JDK 17 jdk.compiler.jmod - Compiler Tool

JDK 17 jdk.compiler.jmod is the JMOD file for JDK 17 Compiler tool, which can be invoked by the "javac" command.

JDK 17 Compiler tool compiled class files are stored in \fyicenter\jdk-17.0.5\jmods\jdk.compiler.jmod.

JDK 17 Compiler tool compiled class files are also linked and stored in the \fyicenter\jdk-17.0.5\lib\modules JImage file.

JDK 17 Compiler source code files are stored in \fyicenter\jdk-17.0.5\lib\src.zip\jdk.compiler.

You can click and view the content of each source code file in the list below.

✍: FYIcenter

com/sun/tools/javac/comp/Analyzer.java

/*
 * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.tools.javac.comp;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Collectors;

import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Kinds.Kind;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
import com.sun.tools.javac.comp.DeferredAttr.AttributionMode;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
import com.sun.tools.javac.tree.JCTree.JCForLoop;
import com.sun.tools.javac.tree.JCTree.JCIf;
import com.sun.tools.javac.tree.JCTree.JCLambda;
import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCNewClass;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCSwitch;
import com.sun.tools.javac.tree.JCTree.JCTry;
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
import com.sun.tools.javac.tree.JCTree.JCUnary;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
import com.sun.tools.javac.tree.JCTree.Tag;
import com.sun.tools.javac.tree.TreeCopier;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.DiagnosticSource;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import com.sun.tools.javac.util.Position;

import static com.sun.tools.javac.code.Flags.GENERATEDCONSTR;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.tree.JCTree.Tag.APPLY;
import static com.sun.tools.javac.tree.JCTree.Tag.FOREACHLOOP;
import static com.sun.tools.javac.tree.JCTree.Tag.LABELLED;
import static com.sun.tools.javac.tree.JCTree.Tag.METHODDEF;
import static com.sun.tools.javac.tree.JCTree.Tag.NEWCLASS;
import static com.sun.tools.javac.tree.JCTree.Tag.NULLCHK;
import static com.sun.tools.javac.tree.JCTree.Tag.TYPEAPPLY;
import static com.sun.tools.javac.tree.JCTree.Tag.VARDEF;

/**
 * Helper class for defining custom code analysis, such as finding instance creation expression
 * that can benefit from diamond syntax.
 */
public class Analyzer {
    protected static final Context.Key<Analyzer> analyzerKey = new Context.Key<>();

    final Types types;
    final Log log;
    final Attr attr;
    final DeferredAttr deferredAttr;
    final ArgumentAttr argumentAttr;
    final TreeMaker make;
    final AnalyzerCopier copier;
    private final boolean allowDiamondWithAnonymousClassCreation;

    final EnumSet<AnalyzerMode> analyzerModes;

    public static Analyzer instance(Context context) {
        Analyzer instance = context.get(analyzerKey);
        if (instance == null)
            instance = new Analyzer(context);
        return instance;
    }

    protected Analyzer(Context context) {
        context.put(analyzerKey, this);
        types = Types.instance(context);
        log = Log.instance(context);
        attr = Attr.instance(context);
        deferredAttr = DeferredAttr.instance(context);
        argumentAttr = ArgumentAttr.instance(context);
        make = TreeMaker.instance(context);
        copier = new AnalyzerCopier();
        Options options = Options.instance(context);
        String findOpt = options.get("find");
        //parse modes
        Source source = Source.instance(context);
        allowDiamondWithAnonymousClassCreation = Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source);
        analyzerModes = AnalyzerMode.getAnalyzerModes(findOpt, source);
    }

    /**
     * This enum defines supported analyzer modes, as well as defining the logic for decoding
     * the {@code -XDfind} option.
     */
    enum AnalyzerMode {
        DIAMOND("diamond", Feature.DIAMOND),
        LAMBDA("lambda", Feature.LAMBDA),
        METHOD("method", Feature.GRAPH_INFERENCE),
        LOCAL("local", Feature.LOCAL_VARIABLE_TYPE_INFERENCE);

        final String opt;
        final Feature feature;

        AnalyzerMode(String opt, Feature feature) {
            this.opt = opt;
            this.feature = feature;
        }

        /**
         * This method is used to parse the {@code find} option.
         * Possible modes are separated by colon; a mode can be excluded by
         * prepending '-' to its name. Finally, the special mode 'all' can be used to
         * add all modes to the resulting enum.
         */
        static EnumSet<AnalyzerMode> getAnalyzerModes(String opt, Source source) {
            if (opt == null) {
                return EnumSet.noneOf(AnalyzerMode.class);
            }
            List<String> modes = List.from(opt.split(","));
            EnumSet<AnalyzerMode> res = EnumSet.noneOf(AnalyzerMode.class);
            if (modes.contains("all")) {
                res = EnumSet.allOf(AnalyzerMode.class);
            }
            for (AnalyzerMode mode : values()) {
                if (modes.contains("-" + mode.opt) || !mode.feature.allowedInSource(source)) {
                    res.remove(mode);
                } else if (modes.contains(mode.opt)) {
                    res.add(mode);
                }
            }
            return res;
        }
    }

    /**
     * A statement analyzer is a work-unit that matches certain AST nodes (of given type {@code S}),
     * rewrites them to different AST nodes (of type {@code T}) and then generates some meaningful
     * messages in case the analysis has been successful.
     */
    abstract class StatementAnalyzer<S extends JCTree, T extends JCTree> {

        AnalyzerMode mode;
        JCTree.Tag tag;

        StatementAnalyzer(AnalyzerMode mode, Tag tag) {
            this.mode = mode;
            this.tag = tag;
        }

        /**
         * Is this analyzer allowed to run?
         */
        boolean isEnabled() {
            return analyzerModes.contains(mode);
        }

        /**
         * Should this analyzer be rewriting the given tree?
         */
        abstract boolean match(S tree);

        /**
         * Rewrite a given AST node into a new one(s)
         */
        abstract List<T> rewrite(S oldTree);

        /**
         * Entry-point for comparing results and generating diagnostics.
         */
        abstract void process(S oldTree, T newTree, boolean hasErrors);
    }

    /**
     * This analyzer checks if generic instance creation expression can use diamond syntax.
     */
    class DiamondInitializer extends StatementAnalyzer<JCNewClass, JCNewClass> {

        DiamondInitializer() {
            super(AnalyzerMode.DIAMOND, NEWCLASS);
        }

        @Override
        boolean match(JCNewClass tree) {
            return tree.clazz.hasTag(TYPEAPPLY) &&
                    !TreeInfo.isDiamond(tree) &&
                    (tree.def == null || allowDiamondWithAnonymousClassCreation);
        }

        @Override
        List<JCNewClass> rewrite(JCNewClass oldTree) {
            if (oldTree.clazz.hasTag(TYPEAPPLY)) {
                JCNewClass nc = copier.copy(oldTree);
                ((JCTypeApply)nc.clazz).arguments = List.nil();
                return List.of(nc);
            } else {
                return List.of(oldTree);
            }
        }

        @Override
        void process(JCNewClass oldTree, JCNewClass newTree, boolean hasErrors) {
            if (!hasErrors) {
                List<Type> inferredArgs, explicitArgs;
                if (oldTree.def != null) {
                    inferredArgs = newTree.def.implementing.nonEmpty()
                                      ? newTree.def.implementing.get(0).type.getTypeArguments()
                                      : newTree.def.extending.type.getTypeArguments();
                    explicitArgs = oldTree.def.implementing.nonEmpty()
                                      ? oldTree.def.implementing.get(0).type.getTypeArguments()
                                      : oldTree.def.extending.type.getTypeArguments();
                } else {
                    inferredArgs = newTree.type.getTypeArguments();
                    explicitArgs = oldTree.type.getTypeArguments();
                }
                for (Type t : inferredArgs) {
                    if (!types.isSameType(t, explicitArgs.head)) {
                        return;
                    }
                    explicitArgs = explicitArgs.tail;
                }
                //exact match
                log.warning(oldTree.clazz, Warnings.DiamondRedundantArgs);
            }
        }
    }

    /**
     * This analyzer checks if anonymous instance creation expression can replaced by lambda.
     */
    class LambdaAnalyzer extends StatementAnalyzer<JCNewClass, JCLambda> {

        LambdaAnalyzer() {
            super(AnalyzerMode.LAMBDA, NEWCLASS);
        }

        @Override
        boolean match (JCNewClass tree){
            Type clazztype = tree.clazz.type;
            return tree.def != null &&
                    clazztype.hasTag(CLASS) &&
                    types.isFunctionalInterface(clazztype.tsym) &&
                    decls(tree.def).length() == 1;
        }
        //where
            private List<JCTree> decls(JCClassDecl decl) {
                ListBuffer<JCTree> decls = new ListBuffer<>();
                for (JCTree t : decl.defs) {
                    if (t.hasTag(METHODDEF)) {
                        JCMethodDecl md = (JCMethodDecl)t;
                        if ((md.getModifiers().flags & GENERATEDCONSTR) == 0) {
                            decls.add(md);
                        }
                    } else {
                        decls.add(t);
                    }
                }
                return decls.toList();
            }

        @Override
        List<JCLambda> rewrite(JCNewClass oldTree){
            JCMethodDecl md = (JCMethodDecl)copier.copy(decls(oldTree.def).head);
            List<JCVariableDecl> params = md.params;
            JCBlock body = md.body;
            JCLambda newTree = make.at(oldTree).Lambda(params, body);
            return List.of(newTree);
        }

        @Override
        void process (JCNewClass oldTree, JCLambda newTree, boolean hasErrors){
            if (!hasErrors) {
                log.warning(oldTree.def, Warnings.PotentialLambdaFound);
            }
        }
    }

    /**
     * This analyzer checks if generic method call has redundant type arguments.
     */
    class RedundantTypeArgAnalyzer extends StatementAnalyzer<JCMethodInvocation, JCMethodInvocation> {

        RedundantTypeArgAnalyzer() {
            super(AnalyzerMode.METHOD, APPLY);
        }

        @Override
        boolean match (JCMethodInvocation tree){
            return tree.typeargs != null &&
                    tree.typeargs.nonEmpty();
        }
        @Override
        List<JCMethodInvocation> rewrite(JCMethodInvocation oldTree){
            JCMethodInvocation app = copier.copy(oldTree);
            app.typeargs = List.nil();
            return List.of(app);
        }

        @Override
        void process (JCMethodInvocation oldTree, JCMethodInvocation newTree, boolean hasErrors){
            if (!hasErrors) {
                //exact match
                log.warning(oldTree, Warnings.MethodRedundantTypeargs);
            }
        }
    }

    /**
     * Base class for local variable inference analyzers.
     */
    abstract class RedundantLocalVarTypeAnalyzerBase<X extends JCStatement> extends StatementAnalyzer<X, X> {

        RedundantLocalVarTypeAnalyzerBase(JCTree.Tag tag) {
            super(AnalyzerMode.LOCAL, tag);
        }

        boolean isImplicitlyTyped(JCVariableDecl decl) {
            return decl.vartype.pos == Position.NOPOS;
        }

        /**
         * Map a variable tree into a new declaration using implicit type.
         */
        JCVariableDecl rewriteVarType(JCVariableDecl oldTree) {
            JCVariableDecl newTree = copier.copy(oldTree);
            newTree.vartype = null;
            return newTree;
        }

        /**
         * Analyze results of local variable inference.
         */
        void processVar(JCVariableDecl oldTree, JCVariableDecl newTree, boolean hasErrors) {
            if (!hasErrors) {
                if (types.isSameType(oldTree.type, newTree.type)) {
                    log.warning(oldTree, Warnings.LocalRedundantType);
                }
            }
        }
    }

    /**
     * This analyzer checks if a local variable declaration has redundant type.
     */
    class RedundantLocalVarTypeAnalyzer extends RedundantLocalVarTypeAnalyzerBase<JCVariableDecl> {

        RedundantLocalVarTypeAnalyzer() {
            super(VARDEF);
        }

        boolean match(JCVariableDecl tree){
            return tree.sym.owner.kind == Kind.MTH &&
                    tree.init != null && !isImplicitlyTyped(tree) &&
                    attr.canInferLocalVarType(tree) == null;
        }
        @Override
        List<JCVariableDecl> rewrite(JCVariableDecl oldTree) {
            return List.of(rewriteVarType(oldTree));
        }
        @Override
        void process(JCVariableDecl oldTree, JCVariableDecl newTree, boolean hasErrors){
            processVar(oldTree, newTree, hasErrors);
        }
    }

    /**
     * This analyzer checks if a for each variable declaration has redundant type.
     */
    class RedundantLocalVarTypeAnalyzerForEach extends RedundantLocalVarTypeAnalyzerBase<JCEnhancedForLoop> {

        RedundantLocalVarTypeAnalyzerForEach() {
            super(FOREACHLOOP);
        }

        @Override
        boolean match(JCEnhancedForLoop tree){
            return !isImplicitlyTyped(tree.var);
        }
        @Override
        List<JCEnhancedForLoop> rewrite(JCEnhancedForLoop oldTree) {
            JCEnhancedForLoop newTree = copier.copy(oldTree);
            newTree.var = rewriteVarType(oldTree.var);
            newTree.body = make.at(oldTree.body).Block(0, List.nil());
            return List.of(newTree);
        }
        @Override
        void process(JCEnhancedForLoop oldTree, JCEnhancedForLoop newTree, boolean hasErrors){
            processVar(oldTree.var, newTree.var, hasErrors);
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    StatementAnalyzer<JCTree, JCTree>[] analyzers = new StatementAnalyzer[] {
            new DiamondInitializer(),
            new LambdaAnalyzer(),
            new RedundantTypeArgAnalyzer(),
            new RedundantLocalVarTypeAnalyzer(),
            new RedundantLocalVarTypeAnalyzerForEach()
    };

    /**
     * Create a copy of Env if needed.
     */
    Env<AttrContext> copyEnvIfNeeded(JCTree tree, Env<AttrContext> env) {
        if (!analyzerModes.isEmpty() &&
                !env.info.attributionMode.isSpeculative &&
                TreeInfo.isStatement(tree) &&
                !tree.hasTag(LABELLED)) {
            Env<AttrContext> analyzeEnv =
                    env.dup(env.tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner)));
            analyzeEnv.info.returnResult = analyzeEnv.info.returnResult != null ?
                    attr.new ResultInfo(analyzeEnv.info.returnResult.pkind,
                                        analyzeEnv.info.returnResult.pt) : null;
            return analyzeEnv;
        } else {
            return null;
        }
    }

    /**
     * Analyze an AST node if needed.
     */
    void analyzeIfNeeded(JCTree tree, Env<AttrContext> env) {
        if (env != null) {
            JCStatement stmt = (JCStatement)tree;
            analyze(stmt, env);
        }
    }

    /**
     * Analyze an AST node; this involves collecting a list of all the nodes that needs rewriting,
     * and speculatively type-check the rewritten code to compare results against previously attributed code.
     */
    protected void analyze(JCStatement statement, Env<AttrContext> env) {
        StatementScanner statementScanner = new StatementScanner(statement, env);
        statementScanner.scan();

        if (!statementScanner.rewritings.isEmpty()) {
            for (RewritingContext rewriting : statementScanner.rewritings) {
                deferredAnalysisHelper.queue(rewriting);
            }
        }
    }

    /**
     * Helper interface to handle deferral of analysis tasks.
     */
    interface DeferredAnalysisHelper {
        /**
         * Add a new analysis task to the queue.
         */
        void queue(RewritingContext rewriting);
        /**
         * Flush queue with given attribution env.
         */
        void flush(Env<AttrContext> flushEnv);
    }

    /**
     * Dummy deferral handler.
     */
    DeferredAnalysisHelper flushDeferredHelper = new DeferredAnalysisHelper() {
        @Override
        public void queue(RewritingContext rewriting) {
            //do nothing
        }

        @Override
        public void flush(Env<AttrContext> flushEnv) {
            //do nothing
        }
    };

    /**
     * Simple deferral handler. All tasks belonging to the same outermost class are added to
     * the same queue. The queue is flushed after flow analysis (only if no error occurred).
     */
    DeferredAnalysisHelper queueDeferredHelper = new DeferredAnalysisHelper() {

        Map<ClassSymbol, Queue<RewritingContext>> Q = new HashMap<>();

        @Override
        public void queue(RewritingContext rewriting) {
            Queue<RewritingContext> s = Q.computeIfAbsent(rewriting.env.enclClass.sym.outermostClass(), k -> new ArrayDeque<>());
            s.add(rewriting);
        }

        @Override
        public void flush(Env<AttrContext> flushEnv) {
            if (!Q.isEmpty()) {
                DeferredAnalysisHelper prevHelper = deferredAnalysisHelper;
                try {
                    deferredAnalysisHelper = flushDeferredHelper;
                    Queue<RewritingContext> rewritings = Q.get(flushEnv.enclClass.sym.outermostClass());
                    while (rewritings != null && !rewritings.isEmpty()) {
                        doAnalysis(rewritings.remove());
                    }
                } finally {
                    deferredAnalysisHelper = prevHelper;
                }
            }
        }
    };

    DeferredAnalysisHelper deferredAnalysisHelper = queueDeferredHelper;

    void doAnalysis(RewritingContext rewriting) {
        DiagnosticSource prevSource = log.currentSource();
        LocalCacheContext localCacheContext = argumentAttr.withLocalCacheContext();
        try {
            log.useSource(rewriting.env.toplevel.getSourceFile());

            JCStatement treeToAnalyze = (JCStatement)rewriting.originalTree;
            JCTree wrappedTree = null;

            if (rewriting.env.info.scope.owner.kind == Kind.TYP) {
                //add a block to hoist potential dangling variable declarations
                treeToAnalyze = make.at(Position.NOPOS)
                                    .Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
                wrappedTree = rewriting.originalTree;
            }

            //TODO: to further refine the analysis, try all rewriting combinations
            deferredAttr.attribSpeculative(treeToAnalyze, rewriting.env, attr.statInfo, new TreeRewriter(rewriting, wrappedTree),
                    () -> rewriting.diagHandler(), AttributionMode.ANALYZER, argumentAttr.withLocalCacheContext());
            rewriting.analyzer.process(rewriting.oldTree, rewriting.replacement, rewriting.erroneous);
        } catch (Throwable ex) {
            Assert.error("Analyzer error when processing: " +
                         rewriting.originalTree + ":" + ex.toString() + "\n" +
                         Arrays.stream(ex.getStackTrace())
                               .map(se -> se.toString())
                               .collect(Collectors.joining("\n")));
        } finally {
            log.useSource(prevSource.getFile());
            localCacheContext.leave();
        }
    }

    public void flush(Env<AttrContext> flushEnv) {
        deferredAnalysisHelper.flush(flushEnv);
    }

    /**
     * Subclass of {@link com.sun.tools.javac.tree.TreeScanner} which visit AST-nodes w/o crossing
     * statement boundaries.
     */
    class StatementScanner extends TreeScanner {
        /** Tree rewritings (generated by analyzers). */
        ListBuffer<RewritingContext> rewritings = new ListBuffer<>();
        JCTree originalTree;
        Env<AttrContext> env;

        StatementScanner(JCTree originalTree, Env<AttrContext> env) {
            this.originalTree = originalTree;
            this.env = attr.copyEnv(env);
        }

        public void scan() {
            scan(originalTree);
        }

        @Override
        @SuppressWarnings("unchecked")
        public void scan(JCTree tree) {
            if (tree != null) {
                for (StatementAnalyzer<JCTree, JCTree> analyzer : analyzers) {
                    if (analyzer.isEnabled() &&
                            tree.hasTag(analyzer.tag) &&
                            analyzer.match(tree)) {
                        for (JCTree t : analyzer.rewrite(tree)) {
                            rewritings.add(new RewritingContext(originalTree, tree, t, analyzer, env));
                        }
                        break; //TODO: cover cases where multiple matching analyzers are found
                    }
                }
            }
            super.scan(tree);
        }

        @Override
        public void visitClassDef(JCClassDecl tree) {
            //do nothing (prevents seeing same stuff twice)
        }

        @Override
        public void visitMethodDef(JCMethodDecl tree) {
            //do nothing (prevents seeing same stuff twice)
        }

        @Override
        public void visitBlock(JCBlock tree) {
            //do nothing (prevents seeing same stuff twice)
        }

        @Override
        public void visitLambda(JCLambda tree) {
            //do nothing (prevents seeing same stuff in lambda expression twice)
        }

        @Override
        public void visitSwitch(JCSwitch tree) {
            scan(tree.getExpression());
        }

        @Override
        public void visitForLoop(JCForLoop tree) {
            //skip body and var decl (to prevents same statements to be analyzed twice)
            scan(tree.getCondition());
            scan(tree.getUpdate());
        }

        @Override
        public void visitTry(JCTry tree) {
            //skip resources (to prevents same statements to be analyzed twice)
            scan(tree.getBlock());
            scan(tree.getCatches());
            scan(tree.getFinallyBlock());
        }

        @Override
        public void visitForeachLoop(JCEnhancedForLoop tree) {
            //skip body (to prevents same statements to be analyzed twice)
            scan(tree.getExpression());
        }

        @Override
        public void visitWhileLoop(JCWhileLoop tree) {
            //skip body (to prevents same statements to be analyzed twice)
            scan(tree.getCondition());
        }

        @Override
        public void visitDoLoop(JCDoWhileLoop tree) {
            //skip body (to prevents same statements to be analyzed twice)
            scan(tree.getCondition());
        }

        @Override
        public void visitIf(JCIf tree) {
            //skip body (to prevents same statements to be analyzed twice)
            scan(tree.getCondition());
        }
    }

    class RewritingContext {
        // the whole tree being analyzed
        JCTree originalTree;
        // a subtree, old tree, that will be rewritten
        JCTree oldTree;
        // the replacement for the old tree
        JCTree replacement;
        // did the compiler find any error
        boolean erroneous;
        // the env
        Env<AttrContext> env;
        // the corresponding analyzer
        StatementAnalyzer<JCTree, JCTree> analyzer;

        RewritingContext(
                JCTree originalTree,
                JCTree oldTree,
                JCTree replacement,
                StatementAnalyzer<JCTree, JCTree> analyzer,
                Env<AttrContext> env) {
            this.originalTree = originalTree;
            this.oldTree = oldTree;
            this.replacement = replacement;
            this.analyzer = analyzer;
            this.env = attr.copyEnv(env);
            /*  this is a temporary workaround that should be removed once we have a truly independent
             *  clone operation
             */
            if (originalTree.hasTag(VARDEF)) {
                // avoid redefinition clashes
                this.env.info.scope.remove(((JCVariableDecl)originalTree).sym);
            }
        }

        /**
         * Simple deferred diagnostic handler which filters out all messages and keep track of errors.
         */
        Log.DeferredDiagnosticHandler diagHandler() {
            return new Log.DeferredDiagnosticHandler(log, d -> {
                if (d.getType() == DiagnosticType.ERROR) {
                    erroneous = true;
                }
                return true;
            });
        }
    }

    /**
     * Subclass of TreeCopier that maps nodes matched by analyzers onto new AST nodes.
     */
    class AnalyzerCopier extends TreeCopier<Void> {

        public AnalyzerCopier() {
            super(make);
        }

        @Override @DefinedBy(Api.COMPILER_TREE)
        public JCTree visitLambdaExpression(LambdaExpressionTree node, Void _unused) {
            JCLambda oldLambda = (JCLambda)node;
            JCLambda newLambda = (JCLambda)super.visitLambdaExpression(node, _unused);
            if (oldLambda.paramKind == ParameterKind.IMPLICIT) {
                //reset implicit lambda parameters (whose type might have been set during attr)
                newLambda.paramKind = ParameterKind.IMPLICIT;
                newLambda.params.forEach(p -> p.vartype = null);
            }
            return newLambda;
        }

        @Override @DefinedBy(Api.COMPILER_TREE)
        public JCTree visitNewClass(NewClassTree node, Void aVoid) {
            JCNewClass oldNewClazz = (JCNewClass)node;
            JCNewClass newNewClazz = (JCNewClass)super.visitNewClass(node, aVoid);
            if (!oldNewClazz.args.isEmpty() && oldNewClazz.args.head.hasTag(NULLCHK)) {
                //workaround to Attr generating trees
                newNewClazz.encl = ((JCUnary)newNewClazz.args.head).arg;
                newNewClazz.args = newNewClazz.args.tail;
            }
            return newNewClazz;
        }
    }

   class TreeRewriter extends AnalyzerCopier {

        RewritingContext rewriting;
        JCTree wrappedTree;

        TreeRewriter(RewritingContext rewriting, JCTree wrappedTree) {
            this.rewriting = rewriting;
            this.wrappedTree = wrappedTree;
        }

        @Override
        @SuppressWarnings("unchecked")
        public <Z extends JCTree> Z copy(Z tree, Void _unused) {
            Z newTree = super.copy(tree, null);
            if (tree != null && tree == rewriting.oldTree) {
                Assert.checkNonNull(rewriting.replacement);
                newTree = (Z)rewriting.replacement;
            }
            return newTree;
        }

        @Override
        public JCTree visitVariable(VariableTree node, Void p) {
            JCTree result = super.visitVariable(node, p);
            if (node == wrappedTree) {
                //The current tree is a field and has been wrapped by a block, so it effectivelly
                //became local variable. If it has some modifiers (except for final), an error
                //would be reported, causing the whole rewrite to fail. Removing the non-final
                //modifiers from the variable here:
                ((JCVariableDecl) result).mods.flags &= Flags.FINAL;
            }
            return result;
        }

    }
}

com/sun/tools/javac/comp/Analyzer.java

 

Or download all of them as a single archive file:

File name: jdk.compiler-17.0.5-src.zip
File size: 1450209 bytes
Release date: 2022-09-13
Download 

 

JDK 17 jdk.crypto.cryptoki.jmod - Crypto KI Module

JDK 17 jdk.charsets.jmod - Charsets Module

JDK 17 JMod/Module Files

⇑⇑ FAQ for JDK (Java Development Kit) 17

2023-10-15, 17762👍, 0💬