/** Wraps a JavaFileObject in a UsageAsInputReportingJavaFileObject, shares existing instances. */ private JavaFileObject map(JavaFileObject item) { if (item == null) { return item; } InputUsageRecord usage = inputUsageRecords.get(item.toUri()); if (usage == null) { usage = new InputUsageRecord(item); inputUsageRecords.put(item.toUri(), usage); } return new UsageAsInputReportingJavaFileObject(item, usage); }
/** Returns the name of JavaFileObject, similar to {@link java.io.File#getName} */ public static String getName(final JavaFileObject fo, final boolean noExt) { assert fo != null; if (fo instanceof Base) { Base baseFileObject = (Base) fo; if (noExt) { return baseFileObject.getName(); } else { StringBuilder sb = new StringBuilder(); sb.append(baseFileObject.getName()); sb.append('.'); // NOI18N sb.append(baseFileObject.getExt()); return sb.toString(); } } try { final URL url = fo.toUri().toURL(); String path = url.getPath(); int index1 = path.lastIndexOf('/'); // NOI18N int len; if (noExt) { final int index2 = path.lastIndexOf('.'); // NOI18N if (index2 > index1) { len = index2; } else { len = path.length(); } } else { len = path.length(); } path = path.substring(index1 + 1, len); return path; } catch (MalformedURLException e) { return null; } }
private String getPackage(JavaFileObject file) throws IOException { Iterable<? extends File> prefixes = ((JavacFileManager) fileManager).getLocation(StandardLocation.SOURCE_PATH); // Figure out the package name by stripping the "-src" prefix and // extracting // the package part of the fullname. String filePath = file.toUri().getPath(); // go absolute filePath = new File(filePath).getCanonicalPath(); int srcDirLength = 0; for (File prefixFile : prefixes) { String prefix = prefixFile.getCanonicalPath(); if (filePath.startsWith(prefix) && prefix.length() > srcDirLength) { srcDirLength = prefix.length(); } } if (srcDirLength > 0) { String fullname = filePath.substring(srcDirLength); assert fullname.endsWith(".ceylon"); fullname = fullname.substring(0, fullname.length() - ".ceylon".length()); fullname = fullname.replace(File.separator, "."); if (fullname.startsWith(".")) fullname = fullname.substring(1); String packageName = Convert.packagePart(fullname); if (!packageName.equals("")) return packageName; } return null; }
private void createBeanInfo(TypeElement classElement) throws Exception { if (verbose) { processingEnv .getMessager() .printMessage( Diagnostic.Kind.NOTE, "Generating BeanInfo for " + classElement.getSimpleName()); } String className = classElement.getSimpleName().toString(); String qualifiedName = classElement.getQualifiedName().toString(); PackageElement packageElement = (PackageElement) classElement.getEnclosingElement(); String packageName = packageElement.getQualifiedName().toString(); Map<String, VariableElement> fields = new HashMap<String, VariableElement>(); Writer writer = null; try { // Build Bean Info TypeElement curClassElement = classElement; do { for (Element e : curClassElement.getEnclosedElements()) { if (e.getKind().equals(ElementKind.FIELD) && !e.getModifiers().contains(Modifier.TRANSIENT) && !e.getModifiers().contains(Modifier.STATIC)) { fields.put(e.getSimpleName().toString(), (VariableElement) e); } } TypeMirror t = curClassElement.getSuperclass(); if (t instanceof DeclaredType) { curClassElement = (TypeElement) ((DeclaredType) t).asElement(); } else { curClassElement = null; } } while (curClassElement != null); VelocityContext vc = new VelocityContext(); vc.put("className", className); vc.put("packageName", packageName); vc.put("fields", fields); // Create source file JavaFileObject jfo = processingEnv.getFiler().createSourceFile(qualifiedName + "BeanInfo"); if (verbose) { processingEnv .getMessager() .printMessage(Diagnostic.Kind.NOTE, "creating source file: " + jfo.toUri()); } writer = jfo.openWriter(); template.merge(vc, writer); } finally { closeQuietly(writer); } }
void emitApplication(ProcessingContext env, ApplicationMetaModel application) throws ProcessingException { PackageElement elt = env.get(application.getHandle()); FQN fqn = new FQN(application.getName(), "Application"); // Writer writer = null; try { JavaFileObject applicationFile = env.createSourceFile(fqn, elt); writer = applicationFile.openWriter(); writer.append("package ").append(fqn.getPackageName()).append(";\n"); // Imports writer.append("import ").append(Tools.getImport(ApplicationDescriptor.class)).append(";\n"); // Open class writer.append("public class ").append(fqn.getSimpleName()).append(" {\n"); // Field writer.append("private final ").append(APPLICATION_DESCRIPTOR).append(" descriptor;\n"); // Constructor writer.append("public ").append(fqn.getSimpleName()).append("() throws Exception {\n"); writer .append("this.descriptor = ") .append(APPLICATION_DESCRIPTOR) .append(".create(getClass());\n"); writer.append("}\n"); // Getter writer.append("public ").append(APPLICATION_DESCRIPTOR).append(" getDescriptor() {\n"); writer.append("return descriptor;\n"); writer.append("}\n"); // Close class writer.append("}\n"); // env.log("Generated application " + fqn.getName() + " as " + applicationFile.toUri()); } catch (IOException e) { throw TemplateMetaModel.CANNOT_WRITE_APPLICATION.failure(e, elt, application.getName()); } finally { Tools.safeClose(writer); } }
public JavaFileObject getJavaFileForOutput( Location location, String className, Kind kind, FileObject sibling) throws IOException { JavaFileObject object = standardJavaFileManager.getJavaFileForOutput(location, className, kind, sibling); if (kind == Kind.CLASS) { className = className.replace("/", "."); String enclosingClassName = className.split("\\$")[0]; String sourceFileName = enclosingClassName.substring(enclosingClassName.lastIndexOf(".") + 1) + ".java"; Optional<PluginSource> source = result.findSource(sourceFileName); Path binaryFile = Paths.get(object.toUri()); URL binaryURL = binaryFile.toUri().toURL(); PluginBinary binary = new PluginBinary(binaryURL, source, Optional.of(className)); result.getBinaries().add(binary); } return object; }
public void report(Diagnostic<? extends JavaFileObject> diagnostic) { final CompilerMessage.Kind kind; switch (diagnostic.getKind()) { case ERROR: kind = BuildMessage.Kind.ERROR; myErrorCount++; break; case MANDATORY_WARNING: case WARNING: case NOTE: kind = BuildMessage.Kind.WARNING; myWarningCount++; break; default: kind = BuildMessage.Kind.INFO; } File sourceFile = null; try { // for eclipse compiler just an attempt to call getSource() may lead to an NPE, // so calling this method under try/catch to avoid induced compiler errors final JavaFileObject source = diagnostic.getSource(); sourceFile = source != null ? Utils.convertToFile(source.toUri()) : null; } catch (Exception e) { LOG.info(e); } final String srcPath = sourceFile != null ? FileUtil.toSystemIndependentName(sourceFile.getPath()) : null; String message = diagnostic.getMessage(Locale.US); if (Utils.IS_TEST_MODE) { LOG.info(message); } myContext.processMessage( new CompilerMessage( BUILDER_NAME, kind, message, srcPath, diagnostic.getStartPosition(), diagnostic.getEndPosition(), diagnostic.getPosition(), diagnostic.getLineNumber(), diagnostic.getColumnNumber())); }
private File getSingleOutputDirectory(final Location loc, final JavaFileObject sourceFile) { if (loc == StandardLocation.CLASS_OUTPUT) { if (myOutputsMap.size() > 1 && sourceFile != null) { // multiple outputs case final File outputDir = findOutputDir(new File(Paths.toURI(sourceFile.toUri().getPath()))); if (outputDir != null) { return outputDir; } } } final Iterable<? extends File> location = getStdManager().getLocation(loc); if (location != null) { final Iterator<? extends File> it = location.iterator(); if (it.hasNext()) { return it.next(); } } return null; }
// Dump classfiles onto disk for all compilation units that where successful // and do not carry a -d none spec, either directly or inherited from Main. @Override public void outputClassFiles(CompilationResult unitResult) { if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) { ClassFile[] classFiles = unitResult.getClassFiles(); boolean generateClasspathStructure = this.fileManager.hasLocation(StandardLocation.CLASS_OUTPUT); String currentDestinationPath = this.destinationPath; File outputLocation = null; if (currentDestinationPath != null) { outputLocation = new File(currentDestinationPath); outputLocation.mkdirs(); } for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) { // retrieve the key and the corresponding classfile ClassFile classFile = classFiles[i]; char[] filename = classFile.fileName(); int length = filename.length; char[] relativeName = new char[length + 6]; System.arraycopy(filename, 0, relativeName, 0, length); System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6); CharOperation.replace(relativeName, '/', File.separatorChar); String relativeStringName = new String(relativeName); if (this.compilerOptions.verbose) { EclipseCompilerImpl.this.out.println( Messages.bind( Messages.compilation_write, new String[] { String.valueOf(this.exportedClassFilesCounter + 1), relativeStringName })); } try { JavaFileObject javaFileForOutput = this.fileManager.getJavaFileForOutput( StandardLocation.CLASS_OUTPUT, new String(filename), JavaFileObject.Kind.CLASS, this.javaFileObjectMap.get(unitResult.compilationUnit)); if (generateClasspathStructure) { if (currentDestinationPath != null) { int index = CharOperation.lastIndexOf(File.separatorChar, relativeName); if (index != -1) { File currentFolder = new File(currentDestinationPath, relativeStringName.substring(0, index)); currentFolder.mkdirs(); } } else { // create the subfolfers is necessary // need a way to retrieve the folders to create String path = javaFileForOutput.toUri().getPath(); int index = path.lastIndexOf('/'); if (index != -1) { File file = new File(path.substring(0, index)); file.mkdirs(); } } } OutputStream openOutputStream = javaFileForOutput.openOutputStream(); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(openOutputStream); bufferedOutputStream.write(classFile.header, 0, classFile.headerOffset); bufferedOutputStream.write(classFile.contents, 0, classFile.contentsOffset); bufferedOutputStream.flush(); bufferedOutputStream.close(); } catch (IOException e) { this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e); } this.logger.logClassFile( generateClasspathStructure, currentDestinationPath, relativeStringName); this.exportedClassFilesCounter++; } this.batchCompiler.lookupEnvironment.releaseClassFiles(classFiles); } }
private void markError( DiagnosticCollector<JavaFileObject> diagnosticsCollector, boolean markerCreation) { for (Diagnostic diagnostic : diagnosticsCollector.getDiagnostics()) { System.out.format("Error on line %d" + " -> ", diagnostic.getLineNumber(), diagnostic); System.out.println(diagnostic.getMessage(null) + "\n"); System.err.println("*** " + diagnostic.toString() + " *** " + diagnostic.getCode()); JavaFileObject source = (JavaFileObject) diagnostic.getSource(); String longFileName = source == null ? null : source.toUri().getPath(); // String shortFileName = source == null ? null : source.getName(); // System.out.println("Error in: " + longFileName); // Path path = new Path(longFileName); // IFile ifile = // ResourcesPlugin.getWorkspace().getRoot().getFile(path); if (diagnostic.getLineNumber() > -1) { File fileToOpen = new File(longFileName); if (fileToOpen.exists() && fileToOpen.isFile()) { final IFileStore fileStore = EFS.getLocalFileSystem().getStore(fileToOpen.toURI()); Display display = PlatformUI.getWorkbench().getDisplay(); display.syncExec( new Runnable() { public void run() { try { IEditorPart part = IDE.openEditorOnFileStore(pag, fileStore); if (part != null) { IEditorInput input = part.getEditorInput(); ifile = ((IFileEditorInput) input).getFile(); // ... use activeProjectName } } catch (PartInitException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } else { // Do something if the file does not exist } } // System.out.format("Error on line %d in %s"+"\n", // diagnostic.getLineNumber(), diagnostic); if (markerCreation == true) { int lnr = (int) diagnostic.getLineNumber(); int startPos = (int) diagnostic.getStartPosition(); int stopPos = (int) diagnostic.getEndPosition(); if (ifile != null) { IMarker marker; try { marker = ifile.createMarker(IMarker.PROBLEM); marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); marker.setAttribute(IMarker.MESSAGE, diagnostic.getMessage(null)); marker.setAttribute(IMarker.LINE_NUMBER, lnr); // if (pos.offset != 0) { // System.out.println(startPos); // System.out.println(stopPos); marker.setAttribute(IMarker.CHAR_START, startPos); marker.setAttribute(IMarker.CHAR_END, stopPos - 1); } catch (CoreException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
/** * Save a compiled class and associated classes to a jar file. * * <p>With a packageName = "" and recursive = false, it will save clazz and any classes compiled * from the same source (I think); this is probably what you want. * * @param packageName package name prefix to search for classes, or "" for all * @param clazz a class that has been previously compiled by this bridge * @param mainClazz a class that will be installed as the "Main-Class" of a runnable jar * @param outStream output stream * @param recursive whether to retrieve classes from rest of the the JavaFileManager hierarchy * @throws FileNotFoundException * @throws IOException */ public void saveToJar( String packageName, Class<?> clazz, Class<?> mainClazz, OutputStream outStream, boolean recursive) throws IOException { JavaFileManager manager = fileManagerCache.get(clazz); List<JavaFileObject> list = new ArrayList<JavaFileObject>(); for (JavaFileObject obj : manager.list( StandardLocation.CLASS_PATH, packageName, Collections.singleton(JavaFileObject.Kind.CLASS), false)) list.add(obj); if (list.iterator().hasNext()) { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); if (mainClazz != null) { manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainClazz.getName()); } manifest .getMainAttributes() .put(new Attributes.Name("X-Rascal-Saved-Class"), clazz.getName()); JarOutputStream target = new JarOutputStream(outStream, manifest); JarEntry entry = new JarEntry("META-INF/"); target.putNextEntry(entry); Collection<String> dirs = new ArrayList<String>(); for (JavaFileObject o : list) { String path = o.toUri().getPath().replace(".", "/"); makeJarDirs(target, dirs, path); entry = new JarEntry(path + ".class"); entry.setTime(o.getLastModified()); target.putNextEntry(entry); try (InputStream stream = o.openInputStream()) { byte[] buffer = new byte[8192]; int c = stream.read(buffer); while (c > -1) { target.write(buffer, 0, c); c = stream.read(buffer); } } target.closeEntry(); } if (mainClazz != null) { String name = mainClazz.getName(); String path = name.replace(".", "/") + ".class"; String dir = path.substring(0, path.lastIndexOf('/')); StringBuilder dirTmp = new StringBuilder(dir.length()); for (String d : dir.split("/")) { dirTmp.append(d); dirTmp.append("/"); String tmp = dirTmp.toString(); if (!dirs.contains(tmp)) { dirs.add(tmp); entry = new JarEntry(tmp); target.putNextEntry(entry); } } entry = new JarEntry(path); target.putNextEntry(entry); try (InputStream stream = mainClazz.getClassLoader().getResourceAsStream(path)) { byte[] buffer = new byte[8192]; int c = stream.read(buffer); while (c > -1) { target.write(buffer, 0, c); c = stream.read(buffer); } } target.closeEntry(); } target.close(); } }
@SuppressWarnings({"unchecked", "ConstantConditions"}) private void manageType(TypeElement enclosingElement, Logger logger) { // Make sure we don't process twice the same type String simpleName = enclosingElement.getSimpleName().toString(); String qualifiedName = enclosingElement.getQualifiedName().toString(); String packageName = Utils.getElementPackageName(enclosingElement); if (managedTypes.contains(qualifiedName)) return; managedTypes.add(qualifiedName); // Prepare the output file try { JavaFileObject classFile = processingEnv.getFiler().createSourceFile(qualifiedName + INJECTOR_SUFFIX); logger.note("Writing " + classFile.toUri().getRawPath()); Writer out = classFile.openWriter(); JavaWriter writer = new JavaWriter(out); writer.emitPackage(packageName); // Initial imports writer .emitImports(AsyncService.class, Injector.class, Message.class, Set.class, HashSet.class) .emitImports( "com.joanzapata.android.asyncservice.api.annotation.OnMessage.Priority", "android.os.Handler", "android.os.Looper") .emitStaticImports( "com.joanzapata.android.asyncservice.api.annotation.OnMessage.Priority.*"); // Generates "public final class XXXInjector extends Injector<XXX>" writer .emitEmptyLine() .beginType( simpleName + INJECTOR_SUFFIX, "class", of(PUBLIC, FINAL), "Injector<" + simpleName + ">"); // Generate a handler to execute runnables on the UI Thread writer .emitEmptyLine() .emitField( "Handler", "__handler", of(PRIVATE, FINAL), "new Handler(Looper.getMainLooper())"); // Keep trace of when a method has received data which is not from cache writer .emitEmptyLine() .emitField( "Set<String>", "__receivedFinalResponses", of(PRIVATE, FINAL), "new HashSet<String>()"); // Generates "protected void inject(XXX target) { ..." writer .emitEmptyLine() .emitAnnotation(Override.class) .beginMethod("void", "inject", of(PROTECTED), simpleName, "target"); // Here, inject all services List<Element> elementsAnnotatedWith = findElementsAnnotatedWith(enclosingElement, InjectService.class); for (Element element : elementsAnnotatedWith) { if (isPublicOrPackagePrivate(element)) { writer.emitStatement( "target.%s = new %s(target)", element.getSimpleName(), element.asType().toString() + AsyncServiceAP.GENERATED_CLASS_SUFFIX); } } // End of inject() writer.endMethod().emitEmptyLine(); // Generates "protected void dispatch(XXX target, Message event)" writer .emitAnnotation(Override.class) .beginMethod( "void", "dispatch", of(PROTECTED), "final " + simpleName, "target", "final " + Message.class.getSimpleName(), "event", Priority.class.getSimpleName(), "priority"); // Once the user has received a "remote" result, make sure no cache is sent anymore writer .emitField( "boolean", "__hasBeenReceivedAlready", of(FINAL), "event.getQuery() != null && __receivedFinalResponses.contains(event.getQuery())") .emitStatement("if (event.isCached() && __hasBeenReceivedAlready) return") .emitStatement( "if (!__hasBeenReceivedAlready && !event.isCached() && priority == LAST) __receivedFinalResponses.add(event.getQuery())"); // Here, dispatch events to methods List<Element> responseReceivers = findElementsAnnotatedWith(enclosingElement, OnMessage.class); for (Element responseReceiver : responseReceivers) { ExecutableElement annotatedMethod = (ExecutableElement) responseReceiver; AnnotationMirror annotationMirror = getAnnotation(annotatedMethod, OnMessage.class); List<? extends VariableElement> parameters = annotatedMethod.getParameters(); if (parameters.size() > 1) logger.error( responseReceiver, "@OnMessage annotated methods can't have more than 1 argument"); // Define event type given parameter or @InjectResponse value List<String> eventTypes; boolean hasArg = parameters.size() == 1; if (hasArg) { TypeMirror typeMirror = parameters.get(0).asType(); eventTypes = asList(typeMirror.toString()); if (hasTypeParameters(processingEnv, typeMirror)) logger.error( parameters.get(0), "You can't receive typed parameters in @OnMessage annotated methods"); } else { List<AnnotationValue> parameterTypeClasses = getAnnotationValue(annotationMirror, "value"); // Validate each parameter type given in the annotation eventTypes = new ArrayList<String>(); for (AnnotationValue value : parameterTypeClasses) { DeclaredType parameterTypeClass = (DeclaredType) value.getValue(); if (parameterTypeClass == null) logger.error( annotatedMethod, "Either declare an argument or give @OnMessage a value."); if (hasTypeParameters(processingEnv, parameterTypeClass)) logger.error( annotatedMethod, annotationMirror, "value", "You can't receive typed parameters in @OnMessage method"); eventTypes.add(parameterTypeClass.toString()); } } // Define whether we should check emitter or not dependeing on the annotation value VariableElement from = getAnnotationValue(annotationMirror, "from"); boolean checkEmitter = !ALL.toString().equals("" + from); // Check the priority of the method VariableElement priorityValue = getAnnotationValue(annotationMirror, "priority"); Priority priority = !LAST.toString().equals("" + priorityValue) ? FIRST : LAST; writer.beginControlFlow("if (priority == %s)", priority); // Write the code to call the user method if (checkEmitter) writer.beginControlFlow("if (event.getEmitter() == getTarget())"); // Create a new inner class for the Runnable to run on UI thread StringWriter buffer = new StringWriter(); JavaWriter inner = new JavaWriter(buffer); inner .emitPackage("") .beginType("Runnable()", "new") .emitAnnotation("Override") .beginMethod("void", "run", of(PUBLIC)); if (hasArg) inner.emitStatement( "target.%s((%s) event.getPayload())", annotatedMethod.getSimpleName(), eventTypes.get(0)); else inner.emitStatement("target.%s()", annotatedMethod.getSimpleName()); inner.endMethod().endType(); // For each type (can be multiple) for (int i = 0; i < eventTypes.size(); i++) { String eventType = eventTypes.get(i); writer .beginControlFlow( "%sif (event.getPayload() instanceof %s)", i != 0 ? "else " : "", eventType) .emitStatement("__handler.post(%s)", buffer.toString()) .endControlFlow(); } if (checkEmitter) writer.endControlFlow(); writer.endControlFlow(); } // End of inject(); writer.endMethod().emitEmptyLine(); // End of file writer.endType(); out.flush(); out.close(); } catch (IOException e) { throw new IllegalStateException("Error while create the injector for " + qualifiedName, e); } }