All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.ajdt.internal.core.builder.EclipseAdapterUtils Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/* *******************************************************************
 * Copyright (c) 1999-2001 Xerox Corporation,
 *               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.internal.core.builder;

import java.io.File;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IProgressListener;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.aspectj.weaver.LintMessage;
import org.aspectj.weaver.World;

public class EclipseAdapterUtils {

	// XXX some cut-and-paste from eclipse sources
	public static String makeLocationContext(ICompilationUnit compilationUnit, IProblem problem) {
		// Extract the erroneous token plus some context around it from the beginning of the first to the end of the last
		// problematic line. Usually, it will be a single line, but not necessarily. After extraction, highlight the
		// erroneous token, "underlining" it withthe appropriate number of carets ('^').
		//
		// This code assumes, that the console font is fixed size.

		// Sanity checks
		int startPosition = problem.getSourceStart();
		int endPosition = problem.getSourceEnd();

		if (startPosition > endPosition || startPosition <= 0 && endPosition <= 0 || compilationUnit == null)
			//return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$
			return "(no source information available)";

		final char SPACE = '\u0020';
		final char MARK = '^';
		final char TAB = '\t';
		char[] source = compilationUnit.getContents();
		// the next code tries to underline the token.....
		// it assumes (for a good display) that token source does not
		// contain any \r \n. This is false on statements !
		// (the code still works but the display is not optimal !)

		// compute the how-much-char we are displaying around the inaccurate token
		int contextStart = startPosition >= source.length ? source.length - 1 : startPosition;
		if (contextStart == -1)
			return "(no source information available)"; // Don't like this - why does it occur? pr152835
		int contextEnd = endPosition >= source.length ? source.length - 1 : endPosition;
		int problemLength = contextEnd - contextStart + 1;
		int trimLeftIndex = 0;
		char c;
		while (
			trimLeftIndex <= problemLength &&
			((c = source[contextStart + trimLeftIndex]) == TAB || c == SPACE)
		) {
			trimLeftIndex++;
		}
		contextStart += trimLeftIndex;
		problemLength -= trimLeftIndex;

		// Find the beginning of the first line containing the problem (contextStart)
		// as well as the relative problem start offset (problemStartOffset) from there
		int problemStartOffset;
		for (problemStartOffset = 0; ; problemStartOffset++) {
			if (contextStart == 0)
				break;
			if ((c = source[contextStart - 1]) == '\n' || c == '\r')
				break;
			contextStart--;
		}

		// Find the end of the last line containing the problem (contextEnd)
		// as well as the relative problem end offset (problemEndOffset) from there
		int problemEndOffset;
		for (problemEndOffset = 0; ; problemEndOffset--) {
			if (contextEnd + 1 >= source.length)
				break;
			if ((c = source[contextEnd + 1]) == '\r' || c == '\n')
				break;
			contextEnd++;
		}

		// Extract the problematic lines of code from the source
		char[] extract = new char[contextEnd - contextStart + 1];
		System.arraycopy(source, contextStart, extract, 0, extract.length);

		// Dedent (left-trim) the first line, i.e. remove leading spaces and tabs
		trimLeftIndex = 0;
		while (
			trimLeftIndex < extract.length &&
			((c = extract[trimLeftIndex]) == TAB || c == SPACE)
		) {
			trimLeftIndex++;
		}
		if (trimLeftIndex >= extract.length)
			return new String(extract) + "\n"; // TODO: Shouldn't it return "" or "\n"?
		System.arraycopy(extract, trimLeftIndex, extract = new char[extract.length - trimLeftIndex], 0, extract.length);
		problemStartOffset -= trimLeftIndex;

		// Insert spaces to reach the error position
		int pos = 0;
		char[] underline = new char[extract.length]; // can't be bigger
		for (int i = 0; i < problemStartOffset; i++)
			underline[pos++] = SPACE;
		// Underline the error position with a '^^^^^' character sequence
		for (int i = 0; i < problemLength; i++)
			underline[pos++] = MARK;

		// Resize to remove trailing NUL characters
		System.arraycopy(underline, 0, underline = new char[problemStartOffset + problemLength], 0, pos);

		return new String(extract) + "\n" + new String(underline); //$NON-NLS-2$ //$NON-NLS-1$
	}

	/**
	 * Extract source location file, start and end lines, and context. Column is not extracted correctly.
	 * @param progressListener
	 *
	 * @return ISourceLocation with correct file and lines but not column.
	 */
	public static ISourceLocation makeSourceLocation(ICompilationUnit unit, IProblem problem, IProgressListener progressListener) {
		int line = problem.getSourceLineNumber();
		File file = new File(new String(problem.getOriginatingFileName()));
		// cheat here...269912 - don't build the context if under IDE control
		if (progressListener!=null) {
			return new SourceLocation(file, line, line, 0, null);
		} else {
			String context = makeLocationContext(unit, problem);
			// XXX 0 column is wrong but recoverable from makeLocationContext
			return new SourceLocation(file, line, line, 0, context);
		}
	}

	/**
	 * Extract message text and source location, including context.
	 *
	 * @param world
	 * @param progressListener
	 */
	public static IMessage makeMessage(ICompilationUnit unit, IProblem problem, World world, IProgressListener progressListener) {
		ISourceLocation sourceLocation = makeSourceLocation(unit, problem, progressListener);
		IProblem[] seeAlso = problem.seeAlso();
		// If the user has turned off classfile line number gen, then we may not be able to tell them
		// about all secondary locations (pr209372)
		int validPlaces = 0;
		for (IProblem value : seeAlso) {
			if (value.getSourceLineNumber() >= 0)
				validPlaces++;
		}
		ISourceLocation[] seeAlsoLocations = new ISourceLocation[validPlaces];
		int pos = 0;
		for (IProblem iProblem : seeAlso) {
			if (iProblem.getSourceLineNumber() >= 0) {
				seeAlsoLocations[pos++] = new SourceLocation(new File(new String(iProblem.getOriginatingFileName())), iProblem
						.getSourceLineNumber());
			}
		}
		// We transform messages from AJ types to eclipse IProblems
		// and back to AJ types. During their time as eclipse problems,
		// we remember whether the message originated from a declare
		// in the extraDetails.
		String extraDetails = problem.getSupplementaryMessageInfo();
		boolean declared = false;
		boolean isLintMessage = false;
		String lintkey = null;
		if (extraDetails != null && extraDetails.endsWith("[deow=true]")) {
			declared = true;
			extraDetails = extraDetails.substring(0, extraDetails.length() - "[deow=true]".length());
		}
		if (extraDetails != null && extraDetails.contains("[Xlint:")) {
			isLintMessage = true;
			lintkey = extraDetails.substring(extraDetails.indexOf("[Xlint:"));
			lintkey = lintkey.substring("[Xlint:".length());
			lintkey = lintkey.substring(0, lintkey.indexOf("]"));
		}

		// If the 'problem' represents a TO DO kind of thing then use the message kind that
		// represents this so AJDT sees it correctly.
		IMessage.Kind kind;
		if (problem.getID() == IProblem.Task) {
			kind = IMessage.TASKTAG;
		} else {
			if (problem.isError()) {
				kind = IMessage.ERROR;
			} else {
				kind = IMessage.WARNING;
			}
		}
		IMessage msg = null;
		if (isLintMessage) {
			msg = new LintMessage(problem.getMessage(), extraDetails, world.getLint().fromKey(lintkey), kind, sourceLocation, null,
					seeAlsoLocations, declared, problem.getID(), problem.getSourceStart(), problem.getSourceEnd());
		} else {
			msg = new Message(problem.getMessage(), extraDetails, kind, sourceLocation, null, seeAlsoLocations, declared, problem
					.getID(), problem.getSourceStart(), problem.getSourceEnd());
		}
		return msg;
	}

	public static IMessage makeErrorMessage(ICompilationUnit unit, String text, Exception ex) {
		ISourceLocation loc = new SourceLocation(new File(new String(unit.getFileName())), 0, 0, 0, "");
		IMessage msg = new Message(text, IMessage.ERROR, ex, loc);
		return msg;
	}

	public static IMessage makeErrorMessage(String srcFile, String text, Exception ex) {
		ISourceLocation loc = new SourceLocation(new File(srcFile), 0, 0, 0, "");
		IMessage msg = new Message(text, IMessage.ERROR, ex, loc);
		return msg;
	}

	private EclipseAdapterUtils() {
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy