org.aspectj.ajdt.ajc.AjdtCommand Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors:
* PARC initial implementation
* ******************************************************************/
package org.aspectj.ajdt.ajc;
import org.aspectj.ajdt.internal.core.builder.*;
import org.aspectj.bridge.*;
import org.aspectj.weaver.Dump;
import org.aspectj.org.eclipse.jdt.internal.core.builder.MissingSourceFileException;
/**
* ICommand adapter for the AspectJ compiler.
* Not thread-safe.
*/
public class AjdtCommand implements ICommand {
/** Message String for any AbortException thrown from ICommand API's */
public static final String ABORT_MESSAGE = "ABORT";
// private boolean canRepeatCommand = true;
AjBuildManager buildManager = null;
String[] savedArgs = null;
/**
* Run AspectJ compiler, wrapping any exceptions thrown as
* ABORT messages (containing ABORT_MESSAGE String).
* @param args the String[] for the compiler
* @param handler the IMessageHandler for any messages
* @see org.aspectj.bridge.ICommand#runCommand(String[], IMessageHandler)
* @return false if handler has errors or the command failed
*/
public boolean runCommand(String[] args, IMessageHandler handler) {
buildManager = new AjBuildManager(handler);
savedArgs = new String[args.length];
System.arraycopy(args, 0, savedArgs, 0, savedArgs.length);
return doCommand(handler, false);
}
/**
* Run AspectJ compiler, wrapping any exceptions thrown as
* ABORT messages (containing ABORT_MESSAGE String).
* @param handler the IMessageHandler for any messages
* @see org.aspectj.bridge.ICommand#repeatCommand(IMessageHandler)
* @return false if handler has errors or the command failed
*/
public boolean repeatCommand(IMessageHandler handler) {
if (null == buildManager) {
MessageUtil.abort(handler, "repeatCommand called before runCommand");
return false;
}
return doCommand(handler, true);
}
/**
* Delegate of both runCommand and repeatCommand.
* This invokes the argument parser each time
* (even when repeating).
* If the parser detects errors, this signals an
* abort with the usage message and returns false.
* @param handler the IMessageHandler sink for any messages
* @param repeat if true, do incremental build, else do batch build
* @return false if handler has any errors or command failed
*/
protected boolean doCommand(IMessageHandler handler, boolean repeat) {
try {
if (handler instanceof IMessageHolder) {
Dump.saveMessageHolder((IMessageHolder) handler);
}
// buildManager.setMessageHandler(handler);
CountingMessageHandler counter = new CountingMessageHandler(handler);
if (counter.hasErrors()) {
return false;
}
// regenerate configuration b/c world might have changed (?)
AjBuildConfig config = genBuildConfig(savedArgs, counter);
if (!config.shouldProceed()) {
return true;
}
if (!config.hasSources()) {
MessageUtil.error(counter, "no sources specified");
}
if (counter.hasErrors()) {
// Do *not* print usage for config errors (just like ECJ does it). Otherwise the user would have to
// scroll up several screens in order to actually see the error messages.
// String usage = BuildArgParser.getUsage();
// MessageUtil.abort(handler, usage);
return false;
}
//System.err.println("errs: " + counter.hasErrors());
boolean result = ((repeat
? buildManager.incrementalBuild(config, handler)
: buildManager.batchBuild(config, handler))
&& !counter.hasErrors());
Dump.dumpOnExit();
return result;
} catch (AbortException ae) {
if (ae.isSilent()) {
throw ae;
} else {
MessageUtil.abort(handler, ABORT_MESSAGE, ae);
}
} catch (MissingSourceFileException t) {
MessageUtil.error(handler, t.getMessage());
} catch (Throwable t) {
MessageUtil.abort(handler, ABORT_MESSAGE, t);
Dump.dumpWithException(t);
}
return false;
}
/**
* This creates a build configuration for the arguments.
* Errors reported to the handler:
*
* - The parser detects some directly
* - The parser grabs some from the error stream
* emitted by its superclass
* - The configuration has a self-test
*
* In the latter two cases, the errors do not have
* a source location context for locating the error.
*/
public static AjBuildConfig genBuildConfig(String[] args, CountingMessageHandler handler) {
BuildArgParser parser = new BuildArgParser(handler);
AjBuildConfig config = parser.genBuildConfig(args);
ISourceLocation location = null;
if (config.getConfigFile() != null) {
location = new SourceLocation(config.getConfigFile(), 0);
}
String message = parser.getOtherMessages(true);
if (null != message) {
IMessage.Kind kind = inferKind(message);
IMessage m = new Message(message, kind, null, location);
handler.handleMessage(m);
}
// message = config.configErrors();
// if (null != message) {
// IMessage.Kind kind = inferKind(message);
// IMessage m = new Message(message, kind, null, location);
// handler.handleMessage(m);
// }
return config;
}
/**
* Heuristically infer the type of output message logged by the AspectJ compiler. This is a simple keyword matcher
* looking for substrings like "[error]", "[warning]", "AspectJ-specific options:", "AspectJ-specific non-standard
* options:", "Warning options:".
*
* @param message AspectJ compiler message
* @return inferred message kind, either of ERROR, WARNING, USAGE, INFO
*/
protected static IMessage.Kind inferKind(String message) { // XXX dubious
if (message.contains("[error]")) {
return IMessage.ERROR;
}
else if (message.contains("[warning]")) {
return IMessage.WARNING;
}
else if (
containsAll(message, "Usage: ", "AspectJ-specific options:", "Classpath options:") ||
containsAll(message, "Warning options:", "-nowarn", "localHiding", "uselessTypeCheck") ||
containsAll(message, "AspectJ-specific non-standard options:", "-XnoInline", "-Xjoinpoints:")
)
{
return IMessage.USAGE;
}
else {
return IMessage.INFO;
}
}
private static boolean containsAll(String message, String... searchStrings) {
for (String searchString : searchStrings)
if (!message.contains(searchString))
return false;
return true;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy