Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javap/SourceWriter.java
38899 views
/*1* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.javap;2627import java.io.BufferedReader;28import java.io.IOException;29import java.io.StringReader;30import java.util.ArrayList;31import java.util.List;32import java.util.Set;33import java.util.SortedMap;34import java.util.SortedSet;35import java.util.TreeMap;36import java.util.TreeSet;37import javax.tools.JavaFileManager;38import javax.tools.JavaFileManager.Location;39import javax.tools.JavaFileObject;40import javax.tools.StandardLocation;4142import com.sun.tools.classfile.Attribute;43import com.sun.tools.classfile.ClassFile;44import com.sun.tools.classfile.Code_attribute;45import com.sun.tools.classfile.ConstantPoolException;46import com.sun.tools.classfile.Instruction;47import com.sun.tools.classfile.LineNumberTable_attribute;48import com.sun.tools.classfile.SourceFile_attribute;495051/**52* Annotate instructions with source code.53*54* <p><b>This is NOT part of any supported API.55* If you write code that depends on this, you do so at your own risk.56* This code and its internal interfaces are subject to change or57* deletion without notice.</b>58*/59public class SourceWriter extends InstructionDetailWriter {60static SourceWriter instance(Context context) {61SourceWriter instance = context.get(SourceWriter.class);62if (instance == null)63instance = new SourceWriter(context);64return instance;65}6667protected SourceWriter(Context context) {68super(context);69context.put(SourceWriter.class, this);70}7172void setFileManager(JavaFileManager fileManager) {73this.fileManager = fileManager;74}7576public void reset(ClassFile cf, Code_attribute attr) {77setSource(cf);78setLineMap(attr);79}8081public void writeDetails(Instruction instr) {82String indent = space(40); // could get from Options?83Set<Integer> lines = lineMap.get(instr.getPC());84if (lines != null) {85for (int line: lines) {86print(indent);87print(String.format(" %4d ", line));88if (line < sourceLines.length)89print(sourceLines[line]);90println();91int nextLine = nextLine(line);92for (int i = line + 1; i < nextLine; i++) {93print(indent);94print(String.format("(%4d)", i));95if (i < sourceLines.length)96print(sourceLines[i]);97println();98}99}100}101}102103public boolean hasSource() {104return (sourceLines.length > 0);105}106107private void setLineMap(Code_attribute attr) {108SortedMap<Integer, SortedSet<Integer>> map =109new TreeMap<Integer, SortedSet<Integer>>();110SortedSet<Integer> allLines = new TreeSet<Integer>();111for (Attribute a: attr.attributes) {112if (a instanceof LineNumberTable_attribute) {113LineNumberTable_attribute t = (LineNumberTable_attribute) a;114for (LineNumberTable_attribute.Entry e: t.line_number_table) {115int start_pc = e.start_pc;116int line = e.line_number;117SortedSet<Integer> pcLines = map.get(start_pc);118if (pcLines == null) {119pcLines = new TreeSet<Integer>();120map.put(start_pc, pcLines);121}122pcLines.add(line);123allLines.add(line);124}125}126}127lineMap = map;128lineList = new ArrayList<Integer>(allLines);129}130131private void setSource(ClassFile cf) {132if (cf != classFile) {133classFile = cf;134sourceLines = splitLines(readSource(cf));135}136}137138private String readSource(ClassFile cf) {139if (fileManager == null)140return null;141142Location location;143if (fileManager.hasLocation((StandardLocation.SOURCE_PATH)))144location = StandardLocation.SOURCE_PATH;145else146location = StandardLocation.CLASS_PATH;147148// Guess the source file for a class from the package name for this149// class and the base of the source file. This avoids having to read150// additional classes to determine the outmost class from any151// InnerClasses and EnclosingMethod attributes.152try {153String className = cf.getName();154SourceFile_attribute sf =155(SourceFile_attribute) cf.attributes.get(Attribute.SourceFile);156if (sf == null) {157report(messages.getMessage("err.no.SourceFile.attribute"));158return null;159}160String sourceFile = sf.getSourceFile(cf.constant_pool);161String fileBase = sourceFile.endsWith(".java")162? sourceFile.substring(0, sourceFile.length() - 5) : sourceFile;163int sep = className.lastIndexOf("/");164String pkgName = (sep == -1 ? "" : className.substring(0, sep+1));165String topClassName = (pkgName + fileBase).replace('/', '.');166JavaFileObject fo =167fileManager.getJavaFileForInput(location,168topClassName,169JavaFileObject.Kind.SOURCE);170if (fo == null) {171report(messages.getMessage("err.source.file.not.found"));172return null;173}174return fo.getCharContent(true).toString();175} catch (ConstantPoolException e) {176report(e);177return null;178} catch (IOException e) {179report(e.getLocalizedMessage());180return null;181}182}183184private static String[] splitLines(String text) {185if (text == null)186return new String[0];187188List<String> lines = new ArrayList<String>();189lines.add(""); // dummy line 0190try {191BufferedReader r = new BufferedReader(new StringReader(text));192String line;193while ((line = r.readLine()) != null)194lines.add(line);195} catch (IOException ignore) {196}197return lines.toArray(new String[lines.size()]);198}199200private int nextLine(int line) {201int i = lineList.indexOf(line);202if (i == -1 || i == lineList.size() - 1)203return - 1;204return lineList.get(i + 1);205}206207private JavaFileManager fileManager;208private ClassFile classFile;209private SortedMap<Integer, SortedSet<Integer>> lineMap;210private List<Integer> lineList;211private String[] sourceLines;212}213214215