javac编译流程(2)处理空值

接上文javac编译流程(1)准备阶段

回到compile方法

public Result compile(String[] argv, Context context) {
        if (stdOut != null) {
            context.put(Log.outKey, stdOut);
        }

        if (stdErr != null) {
            context.put(Log.errKey, stdErr);
        }

        log = Log.instance(context);
		//argv中没有输入信息,即,空值
        if (argv.length == 0) {
        	//创建一个log包装类
            OptionHelper h = new OptionHelper.GrumpyHelper(log) {
                @Override
                public String getOwnName() { return ownName; }
                @Override
                public void put(String name, String value) { }
            };
            try {
            	//调用process打印至控制台,我们上一篇已经分析过了
            	//如果我们没有设置默认输出流,默认为system.out,即,控制台
                Option.HELP.process(h, "-help");
            } catch (Option.InvalidValueException ignore) {
            }
            //返回结束标志符2
            return Result.CMDERR;
        }

process方法,注意是HELP里的process方法,如果直接点击process会跳至另外一个方法

HELP("--help -help", "opt.help", STANDARD, INFO) {
        @Override
        public void process(OptionHelper helper, String option) throws InvalidValueException {
        	//获取log对象
            Log log = helper.getLog();
            //获取指令名,这里为Javac
            String ownName = helper.getOwnName();
            //WriterKind.STDOUT表示标准输入
            //PrefixKind.JAVAC,即,Javac
            log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "msg.usage.header", ownName);
            //打印可用命令和帮助文档
            showHelp(log, OptionKind.STANDARD);
            //进行换行,意义不大
            log.printNewline(WriterKind.STDOUT);
            //进入父类的process方法
            super.process(helper, option);
        }
    }

进入printLines

public void printLines(WriterKind wk, PrefixKind pk, String key, Object... args) {
		//getWriter用于获取对应的流,即,system.out,没什么好讲的
		//我们重点来讲localize
        printRawLines(getWriter(wk), localize(pk, key, args));
    }

跳过包装类,进入getLocalizedString方法

private static String getLocalizedString(List<ResourceBundle> bundles,
                                             String key,
                                             Object... args) {
       String msg = null;
       //bundles是一个本地化的提示信息集合
       for (List<ResourceBundle> l = bundles; l.nonEmpty() && msg == null; l = l.tail) {
           ResourceBundle rb = l.head;
           try {
           	   //如果getString找不到对应的string,会直接报错,即,不会赋值给msg
           	   //所以msg如果找到了对应的打印数据,不会被null覆盖
               msg = rb.getString(key);
           }
           catch (MissingResourceException e) {
               // ignore, try other bundles in list
           }
       }
       if (msg == null) {
           msg = "compiler message file broken: key=" + key +
               " arguments={0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}";
       }
       //使用Java文字格式类返回格式化后的结果
       return MessageFormat.format(msg, args);
    }

这里要讲一下格式化的效果

//格式化前的字符串
"用法: {0} <options> <source files>\n其中, 可能的选项包括:"
//格式化后的字符串
"用法: javac <options> <source files>\n其中, 可能的选项包括:"

效果类似于动态sql语句,回到printRawLines方法,将返回信息逐行打印

public static void printRawLines(PrintWriter writer, String msg) {

        int nl;
        while ((nl = msg.indexOf('\n')) != -1) {
            writer.println(msg.substring(0, nl));
            msg = msg.substring(nl+1);
        }
        if (msg.length() != 0) writer.println(msg);
    }

在这里插入图片描述
最终打印出提示信息的前两行,进入showHelp

private static void showHelp(Log log, OptionKind kind) {
		//创建Comparator用于给流对象排序
        Comparator<Option> comp = new Comparator<Option>() {
        	//默认以英文规则排序
            final Collator collator = Collator.getInstance(Locale.US);
            //只比较首字母
            { collator.setStrength(Collator.PRIMARY); }

            @Override
            //使用上面创建的比较器
            public int compare(Option o1, Option o2) {
                return collator.compare(o1.primaryName, o2.primaryName);
            }
        };
		//获取本类中所有的枚举对象
        getJavaCompilerOptions()
        		//将其转换为流对象
                .stream()
                //对流对象进行筛选,只保留kind等于OptionKind.STANDARD的枚举对象
                .filter(o -> o.kind == kind)
                //使用上面创建的Comparator进行排序
                .sorted(comp)
                //遍历流对象,并调用help方法
                .forEach(o -> {
                    o.help(log);
                });
    }

进入help方法

protected void help(Log log) {
		//localize方法本质上就是getLocalizedString方法,请参考上面的分析
        help(log, log.localize(PrefixKind.JAVAC, descrKey));
    }

进入真正的help方法,主要是做一些格式判断,主要方法为printRawLines,已在上面分析过了,请自行查看

protected void help(Log log, String descr) {
        String synopses = Arrays.stream(names)
                .map(s -> helpSynopsis(s, log))
                .collect(Collectors.joining(", "));

        // If option synopses and description fit on a single line of reasonable length,
        // display using COMPACT_FORMAT
        if (synopses.length() < DEFAULT_SYNOPSIS_WIDTH
                && !descr.contains("\n")
                && (SMALL_INDENT.length() + DEFAULT_SYNOPSIS_WIDTH + 1 + descr.length() <= DEFAULT_MAX_LINE_LENGTH)) {
            log.printRawLines(WriterKind.STDOUT, String.format(COMPACT_FORMAT, synopses, descr));
            return;
        }

        // If option synopses fit on a single line of reasonable length, show that;
        // otherwise, show 1 per line
        if (synopses.length() <= DEFAULT_MAX_LINE_LENGTH) {
            log.printRawLines(WriterKind.STDOUT, SMALL_INDENT + synopses);
        } else {
            for (String name: names) {
                log.printRawLines(WriterKind.STDOUT, SMALL_INDENT + helpSynopsis(name, log));
            }
        }

        // Finally, show the description
        log.printRawLines(WriterKind.STDOUT, LARGE_INDENT + descr.replace("\n", "\n" + LARGE_INDENT));
    }

进入父类的process方法

public void process(OptionHelper helper, String option) throws InvalidValueException {
		//若为无参
        if (argKind == ArgKind.NONE) {
            process(helper, primaryName, option);
        } else {
        	//findSeparator会对参数个数进行判断
            int sep = findSeparator(option);
            process(helper, primaryName, option.substring(sep + 1));
        }
    }

最终的process方法,由于创建OptionHelper时对put方法设为空,且未重写remove方法和handleFileManagerOption方法,该方法没有任何效果(当然,如果执行remove或handleFileManagerOption直接报错也算的话(lll¬ω¬),也许有那么一点点效果ε=ε=ε=┏(゜ロ゜;)┛)

public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
        if (choices != null) {
            if (choiceKind == ChoiceKind.ONEOF) {
                // some clients like to see just one of option+choice set
                for (String s : choices)
                    helper.remove(primaryName + s);
                String opt = primaryName + arg;
                helper.put(opt, opt);
                // some clients like to see option (without trailing ":")
                // set to arg
                String nm = primaryName.substring(0, primaryName.length() - 1);
                helper.put(nm, arg);
            } else {
                // set option+word for each word in arg
                for (String a: arg.split(",+")) {
                    String opt = primaryName + a;
                    helper.put(opt, opt);
                }
            }
        }
        helper.put(primaryName, arg);
        if (group == OptionGroup.FILEMANAGER)
            helper.handleFileManagerOption(this, arg);
    }

至此,处理空值结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值