/* *******************************************************************
 * 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 v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *     PARC     initial implementation 
 * ******************************************************************/

package org.aspectj.ajdt.internal.compiler.problem;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.DeclareAnnotationDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.IfMethodDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.Proceed;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.compiler.lookup.InterTypeMethodBinding;
import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedFieldBinding;
import org.aspectj.bridge.context.CompilationAndWeavingContext;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.aspectj.org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.IPrivilegedHandler;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.DeclareParents;
import org.aspectj.weaver.patterns.DeclareSoft;
import org.aspectj.weaver.patterns.TypePattern;

/**
 * Extends problem reporter to support compiler-side implementation of declare soft. Also overrides error reporting for the need to
 * implement abstract methods to account for inter-type declarations and pointcut declarations. This second job might be better done
 * directly in the SourceTypeBinding/ClassScope classes.
 * 
 * @author Jim Hugunin
 */
public class AjProblemReporter extends ProblemReporter {

	private static final boolean DUMP_STACK = false;

	public EclipseFactory factory;

	public AjProblemReporter(IErrorHandlingPolicy policy, CompilerOptions options, IProblemFactory problemFactory) {
		super(policy, options, problemFactory);
	}

	public void unhandledException(TypeBinding exceptionType, ASTNode location) {
		if (!factory.getWorld().getDeclareSoft().isEmpty()) {
			Shadow callSite = factory.makeShadow(location, referenceContext);
			Shadow enclosingExec = factory.makeShadow(referenceContext);
			// PR 72157 - calls to super / this within a constructor are not part of the cons join point.
			if ((callSite == null) && (enclosingExec.getKind() == Shadow.ConstructorExecution)
					&& (location instanceof ExplicitConstructorCall)) {
				super.unhandledException(exceptionType, location);
				return;
			}
			// System.err.println("about to show error for unhandled exception: " + new String(exceptionType.sourceName()) +
			// " at " + location + " in " + referenceContext);

			for (DeclareSoft d: factory.getWorld().getDeclareSoft()) {
//			for (Iterator<DeclareSoft> i = factory.getWorld().getDeclareSoft().iterator(); i.hasNext();) {
//				DeclareSoft d = (DeclareSoft) i.next();
				// We need the exceptionType to match the type in the declare soft statement
				// This means it must either be the same type or a subtype
				ResolvedType throwException = factory.fromEclipse((ReferenceBinding) exceptionType);
				FuzzyBoolean isExceptionTypeOrSubtype = d.getException().matchesInstanceof(throwException);
				if (!isExceptionTypeOrSubtype.alwaysTrue())
					continue;

				if (callSite != null) {
					FuzzyBoolean match = d.getPointcut().match(callSite);
					if (match.alwaysTrue()) {
						// System.err.println("matched callSite: " + callSite + " with " + d);
						return;
					} else if (!match.alwaysFalse()) {
						// !!! need this check to happen much sooner
						// throw new RuntimeException("unimplemented, shouldn't have fuzzy match here");
					}
				}
				if (enclosingExec != null) {
					FuzzyBoolean match = d.getPointcut().match(enclosingExec);
					if (match.alwaysTrue()) {
						// System.err.println("matched enclosingExec: " + enclosingExec + " with " + d);
						return;
					} else if (!match.alwaysFalse()) {
						// !!! need this check to happen much sooner
						// throw new RuntimeException("unimplemented, shouldn't have fuzzy match here");
					}
				}
			}
		}

		// ??? is this always correct
		if (location instanceof Proceed) {
			return;
		}

		super.unhandledException(exceptionType, location);
	}
	
	public void unhandledExceptionFromAutoClose(TypeBinding exceptionType, ASTNode location) {
		if (!factory.getWorld().getDeclareSoft().isEmpty()) {
			Shadow callSite = factory.makeShadow(location, referenceContext);
			Shadow enclosingExec = factory.makeShadow(referenceContext);
			// PR 72157 - calls to super / this within a constructor are not part of the cons join point.
			if ((callSite == null) && (enclosingExec.getKind() == Shadow.ConstructorExecution)
					&& (location instanceof ExplicitConstructorCall)) {
				super.unhandledException(exceptionType, location);
				return;
			}
			// System.err.println("about to show error for unhandled exception: " + new String(exceptionType.sourceName()) +
			// " at " + location + " in " + referenceContext);

			for (DeclareSoft d: factory.getWorld().getDeclareSoft()) {
//			for (Iterator<DeclareSoft> i = factory.getWorld().getDeclareSoft().iterator(); i.hasNext();) {
//				DeclareSoft d = (DeclareSoft) i.next();
				// We need the exceptionType to match the type in the declare soft statement
				// This means it must either be the same type or a subtype
				ResolvedType throwException = factory.fromEclipse((ReferenceBinding) exceptionType);
				FuzzyBoolean isExceptionTypeOrSubtype = d.getException().matchesInstanceof(throwException);
				if (!isExceptionTypeOrSubtype.alwaysTrue())
					continue;

				if (callSite != null) {
					FuzzyBoolean match = d.getPointcut().match(callSite);
					if (match.alwaysTrue()) {
						// System.err.println("matched callSite: " + callSite + " with " + d);
						return;
					} else if (!match.alwaysFalse()) {
						// !!! need this check to happen much sooner
						// throw new RuntimeException("unimplemented, shouldn't have fuzzy match here");
					}
				}
				if (enclosingExec != null) {
					FuzzyBoolean match = d.getPointcut().match(enclosingExec);
					if (match.alwaysTrue()) {
						// System.err.println("matched enclosingExec: " + enclosingExec + " with " + d);
						return;
					} else if (!match.alwaysFalse()) {
						// !!! need this check to happen much sooner
						// throw new RuntimeException("unimplemented, shouldn't have fuzzy match here");
					}
				}
			}
		}

		// ??? is this always correct
		if (location instanceof Proceed) {
			return;
		}

		super.unhandledExceptionFromAutoClose(exceptionType, location);
	}

	private boolean isPointcutDeclaration(MethodBinding binding) {
		return CharOperation.prefixEquals(PointcutDeclaration.mangledPrefix, binding.selector);
	}

	private boolean isIntertypeDeclaration(MethodBinding binding) {
		return (binding instanceof InterTypeMethodBinding);
	}

	public void abstractMethodCannotBeOverridden(SourceTypeBinding type, MethodBinding concreteMethod) {
		if (isPointcutDeclaration(concreteMethod)) {
			return;
		}
		super.abstractMethodCannotBeOverridden(type, concreteMethod);
	}

	public void inheritedMethodReducesVisibility(SourceTypeBinding type, MethodBinding concreteMethod,
			MethodBinding[] abstractMethods) {
		// if we implemented this method by a public inter-type declaration, then there is no error

		ResolvedType onTypeX = null;
		// If the type is anonymous, look at its supertype
		if (!type.isAnonymousType()) {
			onTypeX = factory.fromEclipse(type);
		} else {
			// Hmmm. If the ITD is on an interface that is being 'instantiated' using an anonymous type,
			// we sort it out elsewhere and don't come into this method -
			// so we don't have to worry about interfaces, just the superclass.
			onTypeX = factory.fromEclipse(type.superclass()); // abstractMethod.declaringClass);
		}
		for (Iterator i = onTypeX.getInterTypeMungersIncludingSupers().iterator(); i.hasNext();) {
			ConcreteTypeMunger m = (ConcreteTypeMunger) i.next();
			ResolvedMember sig = m.getSignature();
			if (!Modifier.isAbstract(sig.getModifiers())) {
				if (ResolvedType.matches(
						AjcMemberMaker.interMethod(sig, m.getAspectType(), sig.getDeclaringType().resolve(factory.getWorld())
								.isInterface()), factory.makeResolvedMember(concreteMethod))) {
					return;
				}
			}
		}

		super.inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
	}

	// if either of the MethodBinding is an ITD, we have already reported it.
	public void staticAndInstanceConflict(MethodBinding currentMethod, MethodBinding inheritedMethod) {
		if (currentMethod instanceof InterTypeMethodBinding)
			return;
		if (inheritedMethod instanceof InterTypeMethodBinding)
			return;
		super.staticAndInstanceConflict(currentMethod, inheritedMethod);
	}

	public void abstractMethodMustBeImplemented(SourceTypeBinding type, MethodBinding abstractMethod) {
		// if this is a PointcutDeclaration then there is no error
		if (isPointcutDeclaration(abstractMethod))
			return;

		if (isIntertypeDeclaration(abstractMethod))
			return; // when there is a problem with an ITD not being implemented, it will be reported elsewhere

		if (CharOperation.prefixEquals("ajc$interField".toCharArray(), abstractMethod.selector)) {
			// ??? think through how this could go wrong
			return;
		}

		// if we implemented this method by an inter-type declaration, then there is no error
		// ??? be sure this is always right
		ResolvedType onTypeX = null;

		// If the type is anonymous, look at its supertype
		if (!type.isAnonymousType()) {
			onTypeX = factory.fromEclipse(type);
		} else {
			// Hmmm. If the ITD is on an interface that is being 'instantiated' using an anonymous type,
			// we sort it out elsewhere and don't come into this method -
			// so we don't have to worry about interfaces, just the superclass.
			onTypeX = factory.fromEclipse(type.superclass()); // abstractMethod.declaringClass);
		}

		if (onTypeX.isRawType())
			onTypeX = onTypeX.getGenericType();

		List<ConcreteTypeMunger> mungers = onTypeX.getInterTypeMungersIncludingSupers();
		for (ConcreteTypeMunger m : mungers) {
			ResolvedMember sig = m.getSignature();
			if (sig != null && !Modifier.isAbstract(sig.getModifiers())) {
				ResolvedMember abstractMember = factory.makeResolvedMember(abstractMethod);
				if (abstractMember.getName().startsWith("ajc$interMethodDispatch")) {
					ResolvedType dType = factory.getWorld().resolve(sig.getDeclaringType(), false);
					if (ResolvedType.matches(AjcMemberMaker.interMethod(sig, m.getAspectType(), dType.isInterface()),
							abstractMember)) {
						return;
					}
				} else {
					// In this case we have something like:
					// interface I {}
					// abstract class C implements I { abstract void foo();}
					// class D extends C {}
					// ITD: public void I.foo() {...}
					// The ITD is providing the implementation of foo in the class D but when checking for whether the abstract
					// method is overridden, we won't be looking at whether the ITD overrides ajc$interMethodDispath$...foo but
					// whether it overrides the foo method from class C
					if (ResolvedType.matches(sig, factory.makeResolvedMember(abstractMethod)))
						return;
				}
			}
		}

		super.abstractMethodMustBeImplemented(type, abstractMethod);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter#disallowedTargetForAnnotation(org.aspectj.org.eclipse
	 * .jdt.internal.compiler.ast.Annotation)
	 */
	public void disallowedTargetForAnnotation(Annotation annotation) {
		// if the annotation's recipient is an ITD, it might be allowed after all...
		if (annotation.recipient instanceof MethodBinding) {
			MethodBinding binding = (MethodBinding) annotation.recipient;
			String name = new String(binding.selector);
			if (name.startsWith("ajc$")) {
				long metaTagBits = annotation.resolvedType.getAnnotationTagBits(); // could be forward reference
				if (name.indexOf("interField") != -1) {
					if ((metaTagBits & TagBits.AnnotationForField) != 0)
						return;
				} else if (name.indexOf("interConstructor") != -1) {
					if ((metaTagBits & TagBits.AnnotationForConstructor) != 0)
						return;
				} else if (name.indexOf("interMethod") != -1) {
					if ((metaTagBits & TagBits.AnnotationForMethod) != 0)
						return;
				} else if (name.indexOf("declare_" + DeclareAnnotation.AT_TYPE + "_") != -1) {
					if ((metaTagBits & TagBits.AnnotationForAnnotationType) != 0 || (metaTagBits & TagBits.AnnotationForType) != 0)
						return;
				} else if (name.indexOf("declare_" + DeclareAnnotation.AT_FIELD + "_") != -1) {
					if ((metaTagBits & TagBits.AnnotationForField) != 0)
						return;
				} else if (name.indexOf("declare_" + DeclareAnnotation.AT_CONSTRUCTOR + "_") != -1) {
					if ((metaTagBits & TagBits.AnnotationForConstructor) != 0)
						return;
				} else if (name.indexOf("declare_eow") != -1) {
					if ((metaTagBits & TagBits.AnnotationForField) != 0)
						return;
				}
			}
		}

		// not our special case, report the problem...
		super.disallowedTargetForAnnotation(annotation);
	}

	public void overridesPackageDefaultMethod(MethodBinding localMethod, MethodBinding inheritedMethod) {
		if (new String(localMethod.selector).startsWith("ajc$"))
			return;
		super.overridesPackageDefaultMethod(localMethod, inheritedMethod);
	}

	public void handle(int problemId, String[] problemArguments, String[] messageArguments, int severity, int problemStartPosition,
			int problemEndPosition, ReferenceContext referenceContext, CompilationResult unitResult) {
		if (severity != ProblemSeverities.Ignore && DUMP_STACK) {
			Thread.dumpStack();
		}
		super.handle(problemId, problemArguments, 
				0, // no message elaboration
				messageArguments, severity, problemStartPosition, problemEndPosition,
				referenceContext, unitResult);
	}

	// PR71076
	public void javadocMissingParamTag(char[] name, int sourceStart, int sourceEnd, int modifiers) {
		boolean reportIt = true;
		String sName = new String(name);
		if (sName.startsWith("ajc$"))
			reportIt = false;
		if (sName.equals("thisJoinPoint"))
			reportIt = false;
		if (sName.equals("thisJoinPointStaticPart"))
			reportIt = false;
		if (sName.equals("thisEnclosingJoinPointStaticPart"))
			reportIt = false;
		if (sName.equals("ajc_aroundClosure"))
			reportIt = false;
		if (reportIt)
			super.javadocMissingParamTag(name, sourceStart, sourceEnd, modifiers);
	}

	public void abstractMethodInAbstractClass(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {

		String abstractMethodName = new String(methodDecl.selector);
		if (abstractMethodName.startsWith("ajc$pointcut")) {
			// This will already have been reported, see: PointcutDeclaration.postParse()
			return;
		}
		String[] arguments = new String[] { new String(type.sourceName()), abstractMethodName };
		super.handle(IProblem.AbstractMethodInAbstractClass, arguments, arguments, methodDecl.sourceStart, methodDecl.sourceEnd,
				this.referenceContext, this.referenceContext == null ? null : this.referenceContext.compilationResult());
	}

	/**
	 * Called when there is an ITD marked @override that doesn't override a supertypes method. The method and the binding are passed
	 * - some information is useful from each. The 'method' knows about source offsets for the message, the 'binding' has the
	 * signature of what the ITD is trying to be in the target class.
	 */
	public void itdMethodMustOverride(AbstractMethodDeclaration method, MethodBinding binding) {
		this.handle(IProblem.MethodMustOverride,
				new String[] { new String(binding.selector), typesAsString(binding.isVarargs(), binding.parameters, false),
						new String(binding.declaringClass.readableName()), },
				new String[] { new String(binding.selector), typesAsString(binding.isVarargs(), binding.parameters, true),
						new String(binding.declaringClass.shortReadableName()), }, method.sourceStart, method.sourceEnd,
				this.referenceContext, this.referenceContext == null ? null : this.referenceContext.compilationResult());
	}

	/**
	 * Overrides the implementation in ProblemReporter and is ITD aware. To report a *real* problem with an ITD marked @override,
	 * the other methodMustOverride() method is used.
	 */
	public void methodMustOverride(AbstractMethodDeclaration method, long complianceLevel) {

		// ignore ajc$ methods
		if (new String(method.selector).startsWith("ajc$"))
			return;
		ResolvedMember possiblyErroneousRm = factory.makeResolvedMember(method.binding);

		ResolvedType onTypeX = factory.fromEclipse(method.binding.declaringClass);
		// Can't use 'getInterTypeMungersIncludingSupers()' since that will exclude abstract ITDs
		// on any super classes - so we have to trawl up ourselves.. I wonder if this problem
		// affects other code in the problem reporter that looks through ITDs...
		ResolvedType supertypeToLookAt = onTypeX.getSuperclass();
		while (supertypeToLookAt != null) {
			List<ConcreteTypeMunger> itMungers = supertypeToLookAt.getInterTypeMungers();
			for (Iterator<ConcreteTypeMunger> i = itMungers.iterator(); i.hasNext();) {
				ConcreteTypeMunger m = (ConcreteTypeMunger) i.next();
				if (m.getMunger()!=null && m.getMunger().getKind()== ResolvedTypeMunger.PrivilegedAccess) {
					continue;
				}
				ResolvedMember sig = m.getSignature();
				if (sig == null)
					continue; // we aren't interested in other kinds of munger
				UnresolvedType dType = sig.getDeclaringType();
				if (dType == null)
					continue;
				ResolvedType resolvedDeclaringType = dType.resolve(factory.getWorld());
				ResolvedMember rm = AjcMemberMaker.interMethod(sig, m.getAspectType(), resolvedDeclaringType.isInterface());
				if (ResolvedType.matches(rm, possiblyErroneousRm)) {
					// match, so dont need to report a problem!
					return;
				}
			}
			supertypeToLookAt = supertypeToLookAt.getSuperclass();
		}
		// report the error...
		super.methodMustOverride(method,complianceLevel);
	}

	private String typesAsString(boolean isVarargs, TypeBinding[] types, boolean makeShort) {
		StringBuffer buffer = new StringBuffer(10);
		for (int i = 0, length = types.length; i < length; i++) {
			if (i != 0)
				buffer.append(", "); //$NON-NLS-1$
			TypeBinding type = types[i];
			boolean isVarargType = isVarargs && i == length - 1;
			if (isVarargType)
				type = ((ArrayBinding) type).elementsType();
			buffer.append(new String(makeShort ? type.shortReadableName() : type.readableName()));
			if (isVarargType)
				buffer.append("..."); //$NON-NLS-1$
		}
		return buffer.toString();
	}

	public void visibilityConflict(MethodBinding currentMethod, MethodBinding inheritedMethod) {
		// Not quite sure if the conditions on this test are right - basically I'm saying
		// DONT WORRY if its ITDs since the error will be reported another way...
		if (isIntertypeDeclaration(currentMethod) && isIntertypeDeclaration(inheritedMethod)
				&& Modifier.isPrivate(currentMethod.modifiers) && Modifier.isPrivate(inheritedMethod.modifiers)) {
			return;
		}
		super.visibilityConflict(currentMethod, inheritedMethod);
	}

	public void unusedPrivateType(TypeDeclaration typeDecl) {
		// don't output unused type warnings for aspects!
		if (typeDecl instanceof AspectDeclaration)
			return;
		if (typeDecl.enclosingType != null && (typeDecl.enclosingType instanceof AspectDeclaration)) {
			AspectDeclaration ad = (AspectDeclaration) typeDecl.enclosingType;
			if (ad.concreteName != null) {
				List<Declare> declares = ad.concreteName.declares;
				for (Iterator<Declare> iter = declares.iterator(); iter.hasNext();) {
					Object dec = iter.next();
					if (dec instanceof DeclareParents) {
						DeclareParents decp = (DeclareParents) dec;
						TypePattern[] newparents = decp.getParents().getTypePatterns();
						for (int i = 0; i < newparents.length; i++) {
							TypePattern pattern = newparents[i];
							UnresolvedType ut = pattern.getExactType();
							if (ut == null)
								continue;
							if (CharOperation.compareWith(typeDecl.binding.signature(), ut.getSignature().toCharArray()) == 0)
								return;
						}
					}
				}
			}
		}
		super.unusedPrivateType(typeDecl);
	}
	
	private final static char[] thisJoinPointName = "thisJoinPoint".toCharArray();
	private final static char[] thisJoinPointStaticPartName = "thisJoinPointStaticPart".toCharArray();
	private final static char[] thisEnclosingJoinPointStaticPartName = "thisEnclosingJoinPointStaticPart".toCharArray();
	private final static char[] thisAspectInstanceName = "thisAspectInstance".toCharArray();

	@Override
	public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location, Scope scope) {
		if (CharOperation.equals(binding.name, thisJoinPointName) ||
			CharOperation.equals(binding.name, thisJoinPointStaticPartName) ||
			CharOperation.equals(binding.name, thisAspectInstanceName) || 
			CharOperation.equals(binding.name, thisEnclosingJoinPointStaticPartName)) {
			// If in advice, this is not a problem
			if (binding.declaringScope!=null && (binding.declaringScope.referenceContext() instanceof AdviceDeclaration ||
												 binding.declaringScope.referenceContext() instanceof IfMethodDeclaration)) {
				return;
			}
		}			
		super.uninitializedLocalVariable(binding, location, scope);
	}
	
	public void abstractMethodInConcreteClass(SourceTypeBinding type) {
		if (type.scope!=null && type.scope.referenceContext instanceof AspectDeclaration) {
			// TODO could put out an Aspect specific message here
			return;
		} 
		super.abstractMethodInConcreteClass(type);
	}

	// Don't warn if there is an ITD method/ctor from a privileged aspect
	public void unusedPrivateField(FieldDeclaration fieldDecl) {
		if (fieldDecl!=null && fieldDecl.binding != null && fieldDecl.binding.declaringClass != null) {
			ReferenceBinding type = fieldDecl.binding.declaringClass;

			ResolvedType weaverType = null;
			if (!type.isAnonymousType()) {
				weaverType = factory.fromEclipse(type);
			} else {
				weaverType = factory.fromEclipse(type.superclass());
			}
			Set checked = new HashSet();
			for (Iterator i = weaverType.getInterTypeMungersIncludingSupers().iterator(); i.hasNext();) {
				ConcreteTypeMunger m = (ConcreteTypeMunger) i.next();
				ResolvedType theAspect = m.getAspectType();
				if (!checked.contains(theAspect)) {
					TypeBinding tb = factory.makeTypeBinding(m.getAspectType());
					// Let's check the privilegedHandler from that aspect
					if (tb instanceof SourceTypeBinding) { // BinaryTypeBinding is also a SourceTypeBinding ;)
						IPrivilegedHandler privilegedHandler = ((SourceTypeBinding) tb).privilegedHandler;
						if (privilegedHandler != null) {
							if (privilegedHandler.definesPrivilegedAccessToField(fieldDecl.binding)) {
								return;
							}
						} else if (theAspect instanceof ReferenceType) {
							// ResolvedMember rm = factory.makeResolvedMember(fieldDecl.binding);
							String fname = new String(fieldDecl.name);
							Collection/* ResolvedMember */privvies = ((ReferenceType) theAspect).getPrivilegedAccesses();
							// On an incremental compile the information is in the bcel delegate
							if (privvies != null) {
								for (Iterator iterator = privvies.iterator(); iterator.hasNext();) {
									ResolvedMember priv = (ResolvedMember) iterator.next();
									if (priv.getName().equals(fname)) {
										return;
									}
								}
							}
						}
					}
					checked.add(theAspect);
				}
			}
		}
		super.unusedPrivateField(fieldDecl);
	}

	public void unusedPrivateMethod(AbstractMethodDeclaration methodDecl) {
		// don't output unused warnings for pointcuts...
		if (!(methodDecl instanceof PointcutDeclaration))
			super.unusedPrivateMethod(methodDecl);
	}

	public void caseExpressionMustBeConstant(Expression expression) {
		if (expression instanceof QualifiedNameReference) {
			QualifiedNameReference qnr = (QualifiedNameReference) expression;
			if (qnr.otherBindings != null && qnr.otherBindings.length > 0 && qnr.otherBindings[0] instanceof PrivilegedFieldBinding) {
				super.signalError(expression.sourceStart, expression.sourceEnd,
						"Fields accessible due to an aspect being privileged can not be used in switch statements");
				referenceContext.tagAsHavingErrors();
				return;
			}
		}
		super.caseExpressionMustBeConstant(expression);
	}

	public void unusedArgument(LocalDeclaration localDecl) {
		// don't warn if this is an aj synthetic arg
		String argType = new String(localDecl.type.resolvedType.signature());
		if (argType.startsWith("Lorg/aspectj/runtime/internal"))
			return;

		// If the unused argument is in a pointcut, don't report the problem (for now... pr148219)
		if (localDecl instanceof Argument) {
			Argument arg = (Argument) localDecl;
			if (arg.binding != null && arg.binding.declaringScope != null) {
				ReferenceContext context = arg.binding.declaringScope.referenceContext();
				if (context != null && context instanceof PointcutDeclaration)
					return;
			}
		}
		if (new String(localDecl.name).startsWith("ajc$")) {
			// Do not report problems for infrastructure variables beyond the users control - pr195090
			return;
		}
		super.unusedArgument(localDecl);
	}

	/**
	 * A side-effect of the way that we handle itds on default methods on top-most implementors of interfaces is that a class
	 * acquiring a final default ITD will erroneously report that it can't override its own member. This method detects that
	 * situation.
	 */
	public void finalMethodCannotBeOverridden(MethodBinding currentMethod, MethodBinding inheritedMethod) {
		if (currentMethod == inheritedMethod)
			return;
		super.finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
	}

	/**
	 * The method verifier is a bit 'keen' and doesn't cope well with ITDMs which are of course to be considered a 'default'
	 * implementation if the target type doesn't supply one. This test may not be complete - it is possible that it should read if
	 * *either* is an ITD...but I dont have a testcase that shows that is required. yet. (pr115788)
	 */
	public void duplicateInheritedMethods(SourceTypeBinding type, MethodBinding inheritedMethod1, MethodBinding inheritedMethod2, boolean isJava8) {
		if (inheritedMethod1 instanceof InterTypeMethodBinding || inheritedMethod2 instanceof InterTypeMethodBinding)
			return;
		if ((inheritedMethod1 instanceof ParameterizedMethodBinding)
				&& ((ParameterizedMethodBinding) inheritedMethod1).original() instanceof InterTypeMethodBinding)
			return;
		if ((inheritedMethod2 instanceof ParameterizedMethodBinding)
				&& ((ParameterizedMethodBinding) inheritedMethod2).original() instanceof InterTypeMethodBinding)
			return;
		super.duplicateInheritedMethods(type, inheritedMethod1, inheritedMethod2, isJava8);
	}

	/**
	 * All problems end up routed through here at some point...
	 */
	public IProblem createProblem(char[] fileName, int problemId, String[] problemArguments, String[] messageArguments,
			int severity, int problemStartPosition, int problemEndPosition, int lineNumber) {
		IProblem problem = super.createProblem(fileName, problemId, problemArguments, messageArguments, severity,
				problemStartPosition, problemEndPosition, lineNumber, 0);
		if (factory.getWorld().isInPinpointMode()) {
			MessageIssued ex = new MessageIssued();
			ex.fillInStackTrace();
			StringWriter sw = new StringWriter();
			ex.printStackTrace(new PrintWriter(sw));
			StringBuffer sb = new StringBuffer();
			sb.append(CompilationAndWeavingContext.getCurrentContext());
			sb.append(sw.toString());
			problem = new PinpointedProblem(problem, sb.toString());
		}
		return problem;
	}

	private static class MessageIssued extends RuntimeException {
		public String getMessage() {
			return "message issued...";
		}
	}

	private static class PinpointedProblem implements IProblem {

		private IProblem delegate;
		private String message;

		public PinpointedProblem(IProblem aProblem, String pinpoint) {
			this.delegate = aProblem;
			// if this was a problem that came via the weaver, it will already have
			// pinpoint info, don't do it twice...
			if (delegate.getMessage().indexOf("message issued...") == -1) {
				this.message = delegate.getMessage() + "\n" + pinpoint;
			} else {
				this.message = delegate.getMessage();
			}
		}

		public String[] getArguments() {
			return delegate.getArguments();
		}

		public int getID() {
			return delegate.getID();
		}

		public String getMessage() {
			return message;
		}

		public char[] getOriginatingFileName() {
			return delegate.getOriginatingFileName();
		}

		public int getSourceEnd() {
			return delegate.getSourceEnd();
		}

		public int getSourceLineNumber() {
			return delegate.getSourceLineNumber();
		}

		public int getSourceStart() {
			return delegate.getSourceStart();
		}

		public boolean isError() {
			return delegate.isError();
		}

		public boolean isWarning() {
			return delegate.isWarning();
		}

		public void setSourceEnd(int sourceEnd) {
			delegate.setSourceEnd(sourceEnd);
		}

		public void setSourceLineNumber(int lineNumber) {
			delegate.setSourceLineNumber(lineNumber);
		}

		public void setSourceStart(int sourceStart) {
			delegate.setSourceStart(sourceStart);
		}

		public void setSeeAlsoProblems(IProblem[] problems) {
			delegate.setSeeAlsoProblems(problems);
		}

		public IProblem[] seeAlso() {
			return delegate.seeAlso();
		}

		public void setSupplementaryMessageInfo(String msg) {
			delegate.setSupplementaryMessageInfo(msg);
		}

		public String getSupplementaryMessageInfo() {
			return delegate.getSupplementaryMessageInfo();
		}

		@Override
		public boolean isInfo() {
			return delegate.isInfo();
		}
	}

	public void duplicateMethodInType(AbstractMethodDeclaration methodDecl, boolean equalParameters, int severity) {
		if (new String(methodDecl.selector).startsWith("ajc$interMethod")) {
			// this is an ITD clash and will be reported in another way by AspectJ (173602)
			return;
		}
		super.duplicateMethodInType(methodDecl, equalParameters, severity);
	}

	// pr246393 - if we are going to complain about privileged, we clearly don't know what is going on, so don't
	// confuse the user
	public void parseErrorInsertAfterToken(int start, int end, int currentKind, char[] errorTokenSource, String errorTokenName,
			String expectedToken) {
		if (expectedToken.equals("privileged") || expectedToken.equals("around")) {
			super.parseErrorNoSuggestion(start, end, currentKind, errorTokenSource, errorTokenName);
		} else {
			super.parseErrorInsertAfterToken(start, end, currentKind, errorTokenSource, errorTokenName, expectedToken);
		}
	}

	public void missingValueForAnnotationMember(Annotation annotation, char[] memberName) {
		if (referenceContext instanceof DeclareAnnotationDeclaration) {
			// If a remover then the values are not necessary
			if (((DeclareAnnotationDeclaration) referenceContext).isRemover()) {
				return;
			}
		}
		super.missingValueForAnnotationMember(annotation, memberName);
	}

}
