package bluej.compiler;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import bluej.Config;
import bluej.compiler.Diagnostic.DiagnosticOrigin;


| A compiler implementation using the Compiler API introduced in Java 6. | | @author Marion Zalk | public class CompilerAPICompiler extends Compiler{ private static final AtomicInteger nextDiagnosticIdentifier = new AtomicInteger(1); public CompilerAPICompiler() { setDebug(true); setDeprecation(true); }
| Compile some source files by using the JavaCompiler API. Allows for the addition of user | options | | @param sources | The files to compile | @param observer | The compilation observer | @param internal | True if compiling BlueJ-generated code (shell files); false if | compiling user code | | @return true if successful | @Override public boolean compile(final File[] sources, final CompileObserver observer, final boolean internal, List<String> userOptions, Charset fileCharset, CompileType type) { boolean result = true; JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); List<String> optionsList = new ArrayList<String>(); if (jc == null) { observer.compilerMessage(new bluej.compiler.Diagnostic(bluej.compiler.Diagnostic.ERROR, "The compiler does not appear to be available."), type); return false; } DiagnosticListener<JavaFileObject> diagListener = new DiagnosticListener<JavaFileObject>() { @Override public void report(Diagnostic<? extends JavaFileObject> diag) { String src = null; if (diag.getSource() != null) { if (Config.isJava17()) { src = diag.getSource().getName(); } else { URI srcUri = sources[0].toURI().resolve(diag.getSource().toUri()); src = new File(srcUri).getPath(); } } int diagType; bluej.compiler.Diagnostic bjDiagnostic; String message = diag.getMessage(null); if (diag.getKind() == Diagnostic.Kind.ERROR) { diagType = bluej.compiler.Diagnostic.ERROR; message = processMessage(src, (int) diag.getLineNumber(), message); long beginCol = diag.getColumnNumber(); long endCol = diag.getEndPosition() - diag.getPosition() + beginCol; if (diag.getEndPosition() == Diagnostic.NOPOS) { endCol = beginCol; } if (diag.getLineNumber() == -1) bjDiagnostic = null; else{ bjDiagnostic = new bluej.compiler.Diagnostic(diagType, message, src, diag.getLineNumber(), beginCol, diag.getLineNumber(), endCol, DiagnosticOrigin.JAVAC, getNewErrorIdentifer()); } } else if (diag.getKind() == Diagnostic.Kind.WARNING) { if (message.startsWith("bootstrap class path not set in conjunction with -source ")) { return; } if (message.startsWith("未与 -source") && message.endsWith("一起设置引导类路径")) { return; } if (message.startsWith("ブートストラップ・クラスパスが-source") && message.endsWith("一緒に設定されていません")){ return; } diagType = bluej.compiler.Diagnostic.WARNING; long beginCol = diag.getColumnNumber(); long endCol = diag.getEndPosition() - diag.getPosition() + beginCol; bjDiagnostic = new bluej.compiler.Diagnostic(diagType, message, src, diag.getLineNumber(), beginCol, diag.getLineNumber(), endCol, DiagnosticOrigin.JAVAC, getNewErrorIdentifer()); } else { diagType = bluej.compiler.Diagnostic.NOTE; bjDiagnostic = new bluej.compiler.Diagnostic(diagType, message); if (internal && (message.endsWith(" uses unchecked or unsafe operations.") || message.endsWith("Some input files use unchecked or unsafe operations.") || message.endsWith("Recompile with -Xlint:unchecked for details."))) { return; } } if (bjDiagnostic != null) observer.compilerMessage(bjDiagnostic, type); } }; try { StandardJavaFileManager sjfm = jc.getStandardFileManager(diagListener, null, fileCharset); List<File> pathList = new ArrayList<File>(); List<File> outputList = new ArrayList<File>(); outputList.add(getDestDir()); pathList.addAll(getClassPath()); sjfm.setLocation(StandardLocation.SOURCE_PATH, outputList); sjfm.setLocation(StandardLocation.CLASS_PATH, pathList); File tempDir = null; if (type.keepClasses()) { sjfm.setLocation(StandardLocation.CLASS_OUTPUT, outputList); } else { tempDir = Files.createTempDirectory("bluej").toFile(); sjfm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tempDir)); } Iterable<? extends JavaFileObject> compilationUnits1 = sjfm.getJavaFileObjectsFromFiles(Arrays.asList(sources)); if (isDebug()) { optionsList.add("-g"); } if (isDeprecation()) { optionsList.add("-deprecation"); } File[] bootClassPath = getBootClassPath(); if (bootClassPath != null && bootClassPath.length != 0) { sjfm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, Arrays.asList(bootClassPath)); } optionsList.addAll(userOptions); result = jc.getTask(null, sjfm, diagListener, optionsList, null, compilationUnits1).call(); sjfm.close(); if (tempDir != null) tempDir.delete(); } catch(IOException e) { e.printStackTrace(System.out); return false; } return result; }
| Processes messages returned from the compiler. This just slightly adjusts the format of some | messages. | | @param src The source file path | @param pos The line number at which the error occurrs | @param message The error message | protected String processMessage(String src, int pos, String message) { String expected = src + ":" + pos + ": "; if (message.startsWith(expected)) { message = message.substring(expected.length()); } if (message.contains("cannot resolve symbol") || message.contains("cannot find symbol") || message.contains("incompatible types")) { int index1, index2; String line2, line3; index1 = message.indexOf('\n'); if (index1 == -1) { return message; } index2 = message.indexOf('\n',index1+1); if (index2 < index1) { line2 = message.substring(index1).trim(); line3 = ""; } else { line2 = message.substring(index1, index2).trim(); line3 = message.substring(index2).trim(); } message = message.substring(0, index1); if (line2.startsWith("found") && line2.indexOf(':') != -1) { message = message +" - found " + line2.substring(line2.indexOf(':') + 2, line2.length()); } if (line3.startsWith("required") && line3.indexOf(':') != -1) { message = message +" but expected " + line3.substring(line3.indexOf(':') + 2, line3.length()); } if (line2.startsWith("symbol") && line2.indexOf(':') != -1) { message = message + " - " + line2.substring(line2.indexOf(':') + 2, line2.length()); } } return message; } public static int getNewErrorIdentifer() { return nextDiagnosticIdentifier.getAndIncrement(); } }
top, use, map, class CompilerAPICompiler

.   CompilerAPICompiler
.   compile
.   report
.   processMessage
.   getNewErrorIdentifer




336 neLoCode + 17 LoComm