don't forget about groovy compiler patchers (IDEADEV-41515)
[fedora-idea.git] / plugins / groovy / rt / src / org / jetbrains / groovy / compiler / rt / GroovycRunner.java
blobf2d9fe39f60ad45b754b9389a48eba0325a00200
1 /*
2 * Copyright 2000-2007 JetBrains s.r.o.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 package org.jetbrains.groovy.compiler.rt;
18 import groovy.lang.GroovyClassLoader;
19 import org.codehaus.groovy.ast.ClassNode;
20 import org.codehaus.groovy.classgen.GeneratorContext;
21 import org.codehaus.groovy.control.*;
22 import org.codehaus.groovy.control.messages.WarningMessage;
23 import org.codehaus.groovy.tools.javac.JavaAwareResolveVisitor;
24 import org.codehaus.groovy.tools.javac.JavaStubGenerator;
26 import java.io.*;
27 import java.net.MalformedURLException;
28 import java.net.URL;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.*;
33 /**
34 * @author: Dmitry.Krasilschikov
35 * @date: 16.04.2007
36 * @noinspection UseOfSystemOutOrSystemErr,CallToPrintStackTrace
39 public class GroovycRunner {
41 public static final String PATCHERS = "patchers";
42 public static final String ENCODING = "encoding";
43 public static final String OUTPUTPATH = "outputpath";
44 public static final String FINAL_OUTPUTPATH = "final_outputpath";
45 public static final String END = "end";
47 public static final String SRC_FILE = "src_file";
48 public static final String COMPILED_START = "%%c";
50 public static final String COMPILED_END = "/%c";
51 public static final String TO_RECOMPILE_START = "%%rc";
53 public static final String TO_RECOMPILE_END = "/%rc";
54 public static final String MESSAGES_START = "%%m";
56 public static final String MESSAGES_END = "/%m";
57 public static final String SEPARATOR = "#%%#%%%#%%%%%%%%%#";
59 //public static final Controller ourController = initController();
60 public static final String PRESENTABLE_MESSAGE = "@#$%@# Presentable:";
61 public static final String CLEAR_PRESENTABLE = "$@#$%^ CLEAR_PRESENTABLE";
63 private GroovycRunner() {
67 private static Controller initController() {
68 if (!"true".equals(System.getProperty("profile.groovy.compiler"))) {
69 return null;
72 try {
73 return new Controller();
75 catch (Exception ex) {
76 ex.printStackTrace();
77 return null;
83 public static void main(String[] args) {
85 if (ourController != null) {
86 try {
87 ourController.startCPUProfiling(ProfilingModes.CPU_SAMPLING, null);
89 catch (Exception e) {
90 e.printStackTrace();
95 if (args.length != 2) {
96 System.err.println("There is no arguments for groovy compiler");
97 return;
100 final boolean forStubs = "stubs".equals(args[0]);
101 final File argsFile = new File(args[1]);
103 if (!argsFile.exists()) {
104 System.err.println("Arguments file for groovy compiler not found");
105 return;
108 try {
109 final CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
110 compilerConfiguration.setOutput(new PrintWriter(System.err));
111 compilerConfiguration.setWarningLevel(WarningMessage.PARANOIA);
113 final List compilerMessages = new ArrayList();
114 final List patchers = new ArrayList();
115 final List srcFiles = new ArrayList();
116 final Map class2File = new HashMap();
118 final String[] finalOutput = new String[1];
119 fillFromArgsFile(argsFile, compilerConfiguration, patchers, compilerMessages, srcFiles, class2File, finalOutput);
120 if (srcFiles.isEmpty()) return;
122 System.out.println(PRESENTABLE_MESSAGE + "Groovy compiler: loading sources...");
123 final CompilationUnit unit = createCompilationUnit(forStubs, compilerConfiguration, finalOutput[0]);
124 addSources(forStubs, srcFiles, unit);
125 runPatchers(patchers, compilerMessages, class2File, unit);
127 System.out.println(PRESENTABLE_MESSAGE + "Groovyc: compiling...");
128 final List compiledFiles = GroovyCompilerWrapper.compile(compilerMessages, forStubs, unit);
129 System.out.println(CLEAR_PRESENTABLE);
131 System.out.println();
132 reportCompiledItems(compiledFiles);
134 System.out.println();
135 if (compiledFiles.isEmpty()) {
136 reportNotCompiledItems(srcFiles);
139 int errorCount = 0;
140 for (int i = 0; i < compilerMessages.size(); i++) {
141 CompilerMessage message = (CompilerMessage)compilerMessages.get(i);
143 if (message.getCategory() == CompilerMessage.ERROR) {
144 if (errorCount > 100) {
145 continue;
147 errorCount++;
150 printMessage(message);
153 catch (Throwable e) {
154 e.printStackTrace();
157 finally {
158 if (ourController != null) {
159 try {
160 ourController.captureSnapshot(ProfilingModes.SNAPSHOT_WITHOUT_HEAP);
161 ourController.stopCPUProfiling();
163 catch (Exception e) {
164 e.printStackTrace();
171 private static String fillFromArgsFile(File argsFile, CompilerConfiguration compilerConfiguration, List patchers, List compilerMessages,
172 List srcFiles, Map class2File, String[] finalOutput) {
173 String moduleClasspath = null;
175 BufferedReader reader = null;
176 FileInputStream stream;
178 try {
179 stream = new FileInputStream(argsFile);
180 reader = new BufferedReader(new InputStreamReader(stream));
182 String line;
184 while ((line = reader.readLine()) != null) {
185 if (!SRC_FILE.equals(line)) {
186 break;
189 final File file = new File(reader.readLine());
190 srcFiles.add(file);
191 while (!END.equals(line = reader.readLine())) {
192 class2File.put(line, file);
197 while (line != null) {
198 if (line.startsWith(PATCHERS)) {
199 String s;
200 while (!END.equals(s = reader.readLine())) {
201 try {
202 final CompilationUnitPatcher patcher = (CompilationUnitPatcher)Class.forName(s).newInstance();
203 patchers.add(patcher);
205 catch (InstantiationException e) {
206 addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
208 catch (IllegalAccessException e) {
209 addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
211 catch (ClassNotFoundException e) {
212 addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
216 else if (line.startsWith(ENCODING)) {
217 compilerConfiguration.setSourceEncoding(reader.readLine());
219 else if (line.startsWith(OUTPUTPATH)) {
220 compilerConfiguration.setTargetDirectory(reader.readLine());
222 else if (line.startsWith(FINAL_OUTPUTPATH)) {
223 finalOutput[0] = reader.readLine();
226 line = reader.readLine();
230 catch (FileNotFoundException e) {
231 e.printStackTrace();
233 catch (IOException e) {
234 e.printStackTrace();
236 finally {
237 try {
238 reader.close();
240 catch (IOException e) {
241 e.printStackTrace();
243 finally {
244 argsFile.delete();
247 return moduleClasspath;
250 private static void addSources(boolean forStubs, List srcFiles, final CompilationUnit unit) {
251 for (int i = 0; i < srcFiles.size(); i++) {
252 final File file = (File)srcFiles.get(i);
253 if (forStubs && file.getName().endsWith(".java")) {
254 // unit.addSources(new File[]{file});
255 continue;
258 unit.addSource(new SourceUnit(file, unit.getConfiguration(), unit.getClassLoader(), unit.getErrorCollector()) {
259 public void parse() throws CompilationFailedException {
260 System.out.println(PRESENTABLE_MESSAGE + "Parsing " + file.getName() + "...");
261 super.parse();
262 System.out.println(CLEAR_PRESENTABLE);
268 private static void runPatchers(List patchers, List compilerMessages, Map class2File, CompilationUnit unit) {
269 if (!patchers.isEmpty()) {
270 final PsiAwareResourceLoader loader = new PsiAwareResourceLoader(class2File);
271 for (int i = 0; i < patchers.size(); i++) {
272 final CompilationUnitPatcher patcher = (CompilationUnitPatcher)patchers.get(i);
273 try {
274 patcher.patchCompilationUnit(unit, loader);
276 catch (LinkageError e) {
277 addExceptionInfo(compilerMessages, e, "Couldn't run " + patcher.getClass().getName());
283 private static void reportNotCompiledItems(Collection toRecompile) {
284 for (Iterator iterator = toRecompile.iterator(); iterator.hasNext();) {
285 File file = (File)iterator.next();
286 System.out.print(TO_RECOMPILE_START);
287 System.out.print(file.getAbsolutePath());
288 System.out.print(TO_RECOMPILE_END);
289 System.out.println();
293 private static void reportCompiledItems(List compiledFiles) {
294 for (int i = 0; i < compiledFiles.size(); i++) {
296 * output path
297 * source file
298 * output root directory
300 GroovyCompilerWrapper.OutputItem compiledOutputItem = (GroovyCompilerWrapper.OutputItem)compiledFiles.get(i);
301 System.out.print(COMPILED_START);
302 System.out.print(compiledOutputItem.getOutputPath());
303 System.out.print(SEPARATOR);
304 System.out.print(compiledOutputItem.getSourceFile());
305 System.out.print(SEPARATOR);
306 System.out.print(compiledOutputItem.getOutputRootDirectory());
307 System.out.print(COMPILED_END);
308 System.out.println();
312 private static void printMessage(CompilerMessage message) {
313 System.out.print(MESSAGES_START);
314 System.out.print(message.getCategory());
315 System.out.print(SEPARATOR);
316 System.out.print(message.getMessage());
317 System.out.print(SEPARATOR);
318 System.out.print(message.getUrl());
319 System.out.print(SEPARATOR);
320 System.out.print(message.getLineNum());
321 System.out.print(SEPARATOR);
322 System.out.print(message.getColumnNum());
323 System.out.print(SEPARATOR);
324 System.out.print(MESSAGES_END);
325 System.out.println();
328 private static void addExceptionInfo(List compilerMessages, Throwable e, String message) {
329 final StringWriter writer = new StringWriter();
330 e.printStackTrace(new PrintWriter(writer));
331 compilerMessages.add(new CompilerMessage(CompilerMessage.WARNING, message + ":\n" + writer, "<exception>", -1, -1));
334 private static CompilationUnit createCompilationUnit(final boolean forStubs, final CompilerConfiguration config, final String finalOutput) {
335 config.setClasspath("");
337 final GroovyClassLoader classLoader = buildClassLoaderFor(config);
339 final GroovyClassLoader transformLoader = new GroovyClassLoader(classLoader) {
340 public Enumeration getResources(String name) throws IOException {
341 if (name.endsWith("org.codehaus.groovy.transform.ASTTransformation")) {
342 final Enumeration resources = super.getResources(name);
343 final ArrayList list = Collections.list(resources);
344 for (Iterator iterator = list.iterator(); iterator.hasNext();) {
345 final String file = ((URL)iterator.next()).getFile();
346 if (file.contains(finalOutput)) {
347 iterator.remove();
350 return Collections.enumeration(list);
352 return super.getResources(name);
355 CompilationUnit unit;
356 try {
357 unit = new CompilationUnit(config, null, classLoader, transformLoader) {
359 public void gotoPhase(int phase) throws CompilationFailedException {
360 super.gotoPhase(phase);
361 if (phase <= Phases.ALL) {
362 System.out.println(PRESENTABLE_MESSAGE + (forStubs ? "Groovy stub generator: " : "Groovy compiler: ") + getPhaseDescription());
367 catch (NoSuchMethodError e) {
368 //groovy 1.5.x
369 unit = new CompilationUnit(config, null, classLoader) {
371 public void gotoPhase(int phase) throws CompilationFailedException {
372 super.gotoPhase(phase);
373 if (phase <= Phases.ALL) {
374 System.out.println(PRESENTABLE_MESSAGE + (forStubs ? "Groovy stub generator: " : "Groovy compiler: ") + getPhaseDescription());
379 if (forStubs) {
380 try {
381 addStubGeneration(config, unit);
383 catch (LinkageError e) {
384 //older groovy distributions, just don't generate stubs
387 return unit;
390 private static void addStubGeneration(CompilerConfiguration config, final CompilationUnit unit) {
391 //todo reuse JavaStubCompilationUnit in groovy 1.7
392 boolean useJava5 = config.getTargetBytecode().equals(CompilerConfiguration.POST_JDK5);
393 final JavaStubGenerator stubGenerator = new JavaStubGenerator(config.getTargetDirectory(), false, useJava5);
395 //but JavaStubCompilationUnit doesn't have this...
396 unit.addPhaseOperation(new CompilationUnit.PrimaryClassNodeOperation() {
397 public void call(SourceUnit source, GeneratorContext context, ClassNode node) throws CompilationFailedException {
398 new JavaAwareResolveVisitor(unit).startResolving(node, source);
400 }, Phases.CONVERSION);
402 unit.addPhaseOperation(new CompilationUnit.PrimaryClassNodeOperation() {
403 public void call(final SourceUnit source, final GeneratorContext context, final ClassNode node) throws CompilationFailedException {
404 final String name = node.getNameWithoutPackage();
405 if ("package-info".equals(name)) {
406 return;
409 System.out.println(PRESENTABLE_MESSAGE + "Generating stub for " + name);
410 try {
411 stubGenerator.generateClass(node);
413 catch (FileNotFoundException e) {
414 source.addException(e);
417 },Phases.CONVERSION);
420 static GroovyClassLoader buildClassLoaderFor(final CompilerConfiguration compilerConfiguration) {
421 return (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
422 public Object run() {
423 return new GroovyClassLoader(getClass().getClassLoader(), compilerConfiguration) {
424 public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript)
425 throws ClassNotFoundException, CompilationFailedException {
426 try {
427 return super.loadClass(name, lookupScriptFiles, preferClassOverScript);
429 catch (NoClassDefFoundError e) {
430 final String ncdfe = e.getMessage();
432 throw new RuntimeException("Groovyc error: " + ncdfe + " class not found while resolving class " + name + "; try compiling " + ncdfe + " explicitly", e);
434 catch (LinkageError e) {
435 throw new RuntimeException("Problem loading class " + name, e);