/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.internal.corext.refactoring;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;

import org.eclipse.core.resources.IProject;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NameQualifiedType;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.manipulation.TypeNameMatchCollector;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameMatch;

import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.dom.ASTFlattener;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.dom.Selection;
import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;

public class TypeContextChecker {
	private static class MethodTypesChecker {

		private static final String METHOD_NAME= "__$$__"; //$NON-NLS-1$

		private final IMethod fMethod;
		private final StubTypeContext fStubTypeContext;
		private final List<ParameterInfo> fParameterInfos;
		private final ReturnTypeInfo fReturnTypeInfo;

		public MethodTypesChecker(IMethod method, StubTypeContext stubTypeContext, List<ParameterInfo> parameterInfos, ReturnTypeInfo returnTypeInfo) {
			fMethod= method;
			fStubTypeContext= stubTypeContext;
			fParameterInfos= parameterInfos;
			fReturnTypeInfo= returnTypeInfo;
		}

		public RefactoringStatus[] checkAndResolveMethodTypes() throws CoreException {
			RefactoringStatus[] results= new MethodTypesSyntaxChecker(fMethod, fParameterInfos, fReturnTypeInfo).checkSyntax();
			for (RefactoringStatus result : results) {
				if (result != null && result.hasFatalError()) {
					return results;
				}
			}

			int parameterCount= fParameterInfos.size();
			String[] types= new String[parameterCount + 1];
			for (int i= 0; i < parameterCount; i++)
				types[i]= ParameterInfo.stripEllipsis((fParameterInfos.get(i)).getNewTypeName());
			types[parameterCount]= fReturnTypeInfo.getNewTypeName();
			RefactoringStatus[] semanticsResults= new RefactoringStatus[parameterCount + 1];
			ITypeBinding[] typeBindings= resolveBindings(types, semanticsResults, true);

			boolean needsSecondPass= false;
			for (int i= 0; i < types.length; i++)
				if (typeBindings[i] == null || ! semanticsResults[i].isOK())
					needsSecondPass= true;

			RefactoringStatus[] semanticsResults2= new RefactoringStatus[parameterCount + 1];
			if (needsSecondPass)
				typeBindings= resolveBindings(types, semanticsResults2, false);

			for (int i= 0; i < fParameterInfos.size(); i++) {
				ParameterInfo parameterInfo= fParameterInfos.get(i);
				if (!parameterInfo.isResolve())
					continue;
				if (parameterInfo.getOldTypeBinding() != null && ! parameterInfo.isTypeNameChanged()) {
					parameterInfo.setNewTypeBinding(parameterInfo.getOldTypeBinding());
				} else {
					parameterInfo.setNewTypeBinding(typeBindings[i]);
					if (typeBindings[i] == null || (needsSecondPass && ! semanticsResults2[i].isOK())) {
						if (results[i] == null)
							results[i]= semanticsResults2[i];
						else
							results[i].merge(semanticsResults2[i]);
					}
				}
			}
			fReturnTypeInfo.setNewTypeBinding(typeBindings[fParameterInfos.size()]);
			if (typeBindings[parameterCount] == null || (needsSecondPass && ! semanticsResults2[parameterCount].isOK())) {
				if (results[parameterCount] == null)
					results[parameterCount]= semanticsResults2[parameterCount];
				else
					results[parameterCount].merge(semanticsResults2[parameterCount]);
			}

			return results;
		}

		private ITypeBinding[] resolveBindings(String[] types, RefactoringStatus[] results, boolean firstPass) throws CoreException {
			//TODO: split types into parameterTypes and returnType
			int parameterCount= types.length - 1;
			ITypeBinding[] typeBindings= new ITypeBinding[types.length];

			StringBuilder cuString= new StringBuilder();
			cuString.append(fStubTypeContext.getBeforeString());
			int offsetBeforeMethodName= appendMethodDeclaration(cuString, types, parameterCount);
			cuString.append(fStubTypeContext.getAfterString());

			// need a working copy to tell the parser where to resolve (package visible) types
			ICompilationUnit wc= fMethod.getCompilationUnit().getWorkingCopy(new WorkingCopyOwner() {/*subclass*/}, new NullProgressMonitor());
			try {
				wc.getBuffer().setContents(cuString.toString());
				CompilationUnit compilationUnit= new RefactoringASTParser(IASTSharedValues.SHARED_AST_LEVEL).parse(wc, true);
				ASTNode method= NodeFinder.perform(compilationUnit, offsetBeforeMethodName, METHOD_NAME.length()).getParent();
				Type[] typeNodes= new Type[types.length];
				if (method instanceof MethodDeclaration) {
					MethodDeclaration methodDeclaration= (MethodDeclaration) method;
					typeNodes[parameterCount]= methodDeclaration.getReturnType2();
					List<SingleVariableDeclaration> parameters= methodDeclaration.parameters();
					for (int i= 0; i < parameterCount; i++)
						typeNodes[i]= parameters.get(i).getType();

				} else if (method instanceof AnnotationTypeMemberDeclaration) {
					typeNodes[0]= ((AnnotationTypeMemberDeclaration) method).getType();
				}

				for (int i= 0; i < types.length; i++) {
					Type type= typeNodes[i];
					if (type == null) {
						String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_couldNotResolveType, BasicElementLabels.getJavaElementName(types[i]));
						results[i]= RefactoringStatus.createErrorStatus(msg);
						continue;
					}
					results[i]= new RefactoringStatus();
					for (IProblem problem : ASTNodes.getProblems(type, ASTNodes.NODE_ONLY, ASTNodes.PROBLEMS)) {
						if (isError(problem, type)) {
							results[i].addError(problem.getMessage());
						}
					}
					ITypeBinding binding= handleBug84585(type.resolveBinding());
					if (firstPass && (binding == null || binding.isRecovered())) {
						types[i]= qualifyTypes(type, results[i]);
					}
					typeBindings[i]= binding;
				}
				return typeBindings;
			} finally {
				wc.discardWorkingCopy();
			}
		}

		/**
		 * Decides if a problem matters.
		 * @param problem the problem
		 * @param type the current type
		 * @return return if a problem matters.
		 */
		private boolean isError(IProblem problem, Type type) {
			return true;
		}

		private int appendMethodDeclaration(StringBuilder cuString, String[] types, int parameterCount) throws JavaModelException {
			int flags= fMethod.getFlags();
			if (Flags.isStatic(flags)) {
				cuString.append("static "); //$NON-NLS-1$
			} else if (Flags.isDefaultMethod(flags)) {
				cuString.append("default "); //$NON-NLS-1$
			}

			ITypeParameter[] methodTypeParameters= fMethod.getTypeParameters();
			if (methodTypeParameters.length != 0) {
				cuString.append('<');
				for (int i= 0; i < methodTypeParameters.length; i++) {
					ITypeParameter typeParameter= methodTypeParameters[i];
					if (i > 0)
						cuString.append(',');
					cuString.append(typeParameter.getElementName());
				}
				cuString.append("> "); //$NON-NLS-1$
			}

			cuString.append(types[parameterCount]).append(' ');
			int offsetBeforeMethodName= cuString.length();
			cuString.append(METHOD_NAME).append('(');
			for (int i= 0; i < parameterCount; i++) {
				if (i > 0)
					cuString.append(',');
				cuString.append(types[i]).append(" p").append(i); //$NON-NLS-1$
			}
			cuString.append(");"); //$NON-NLS-1$

			return offsetBeforeMethodName;
		}

		private String qualifyTypes(Type type, final RefactoringStatus result) throws CoreException {
			class NestedException extends RuntimeException {
				private static final long serialVersionUID= 1L;
				NestedException(CoreException e) {
					super(e);
				}
			}
			ASTFlattener flattener= new ASTFlattener() {
				@Override
				public boolean visit(SimpleName node) {
					appendResolved(node.getIdentifier());
					return false;
				}
				@Override
				public boolean visit(QualifiedName node) {
					appendResolved(node.getFullyQualifiedName());
					return false;
				}
				@Override
				public boolean visit(QualifiedType node) {
					appendResolved(ASTNodes.getQualifiedTypeName(node));
					return false;
				}
				@Override
				public boolean visit(NameQualifiedType node) {
					appendResolved(ASTNodes.getQualifiedTypeName(node));
					return false;
				}
				private void appendResolved(String typeName) {
					String resolvedType;
					try {
						resolvedType= resolveType(typeName, result, fMethod.getDeclaringType(), null);
					} catch (CoreException e) {
						throw new NestedException(e);
					}
					this.fBuffer.append(resolvedType);
				}
			};
			try {
				type.accept(flattener);
			} catch (NestedException e) {
				throw ((CoreException) e.getCause());
			}
			return flattener.getResult();
		}

		private static String resolveType(String elementTypeName, RefactoringStatus status, IType declaringType, IProgressMonitor pm) throws CoreException {
			String[][] fqns= declaringType.resolveType(elementTypeName);
			if (fqns != null) {
				if (fqns.length == 1) {
					return JavaModelUtil.concatenateName(fqns[0][0], fqns[0][1]);
				} else if (fqns.length > 1){
					String[] keys= { BasicElementLabels.getJavaElementName(elementTypeName), String.valueOf(fqns.length)};
					String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_ambiguous, keys);
					status.addError(msg);
					return elementTypeName;
				}
			}

			List<TypeNameMatch> typeRefsFound= findTypeInfos(elementTypeName, declaringType, pm);
			if (typeRefsFound.isEmpty()){
				String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_not_unique, BasicElementLabels.getJavaElementName(elementTypeName));
				status.addError(msg);
				return elementTypeName;
			} else if (typeRefsFound.size() == 1){
				TypeNameMatch typeInfo= typeRefsFound.get(0);
				return typeInfo.getFullyQualifiedName();
			} else {
				Assert.isTrue(typeRefsFound.size() > 1);
				String[] keys= {BasicElementLabels.getJavaElementName(elementTypeName), String.valueOf(typeRefsFound.size())};
				String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_ambiguous, keys);
				status.addError(msg);
				return elementTypeName;
			}
		}

		private static List<TypeNameMatch> findTypeInfos(String typeName, IType contextType, IProgressMonitor pm) throws JavaModelException {
			IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaProject[]{contextType.getJavaProject()}, true);
			IPackageFragment currPackage= contextType.getPackageFragment();
			ArrayList<TypeNameMatch> collectedInfos= new ArrayList<>();
			TypeNameMatchCollector requestor= new TypeNameMatchCollector(collectedInfos);
			int matchMode= SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
			new SearchEngine().searchAllTypeNames(null, matchMode, typeName.toCharArray(), matchMode, IJavaSearchConstants.TYPE, scope, requestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, pm);

			List<TypeNameMatch> result= new ArrayList<>();
			for (TypeNameMatch curr : collectedInfos) {
				IType type= curr.getType();
				if (type != null) {
					boolean visible=true;
					try {
						visible= JavaModelUtil.isVisible(type, currPackage);
					} catch (JavaModelException e) {
						//Assume visibile if not available
					}
					if (visible) {
						result.add(curr);
					}
				}
			}
			return result;
		}

	}

	private static class MethodTypesSyntaxChecker {

		private final IMethod fMethod;
		private final List<ParameterInfo> fParameterInfos;
		private final ReturnTypeInfo fReturnTypeInfo;

		public MethodTypesSyntaxChecker(IMethod method, List<ParameterInfo> parameterInfos, ReturnTypeInfo returnTypeInfo) {
			fMethod= method;
			fParameterInfos= parameterInfos;
			fReturnTypeInfo= returnTypeInfo;
		}

		public RefactoringStatus[] checkSyntax() {
			int parameterCount= fParameterInfos.size();
			RefactoringStatus[] results= new RefactoringStatus[parameterCount + 1];
			results[parameterCount]= checkReturnTypeSyntax();
			for (int i= 0; i < parameterCount; i++) {
				ParameterInfo info= fParameterInfos.get(i);
				if (!info.isDeleted())
					results[i]= checkParameterTypeSyntax(info);
			}
			return results;
		}

		private RefactoringStatus checkParameterTypeSyntax(ParameterInfo info) {
			if (!info.isAdded() && !info.isTypeNameChanged() && !info.isDeleted())
				return null;
			return TypeContextChecker.checkParameterTypeSyntax(info.getNewTypeName(), fMethod.getJavaProject());
		}

		private RefactoringStatus checkReturnTypeSyntax() {
			String newTypeName= fReturnTypeInfo.getNewTypeName();
			if ("".equals(newTypeName.trim())) { //$NON-NLS-1$
				String msg= RefactoringCoreMessages.TypeContextChecker_return_type_not_empty;
				return RefactoringStatus.createFatalErrorStatus(msg);
			}
			List<String> problemsCollector= new ArrayList<>(0);
			Type parsedType= parseType(newTypeName, fMethod.getJavaProject(), problemsCollector);
			if (parsedType == null) {
				String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_invalid_return_type, BasicElementLabels.getJavaElementName(newTypeName));
				return RefactoringStatus.createFatalErrorStatus(msg);
			}
			if (problemsCollector.isEmpty())
				return null;

			RefactoringStatus result= new RefactoringStatus();
			for (String problem : problemsCollector) {
				String[] keys= new String[]{ BasicElementLabels.getJavaElementName(newTypeName), BasicElementLabels.getJavaElementName(problem)};
				String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_invalid_return_type_syntax, keys);
				result.addError(msg);
			}
			return result;
		}

		private static boolean isVoidArrayType(Type type){
			if (! type.isArrayType())
				return false;

			ArrayType arrayType= (ArrayType)type;
			if (! arrayType.getElementType().isPrimitiveType())
				return false;
			PrimitiveType primitiveType= (PrimitiveType) arrayType.getElementType();
			return (primitiveType.getPrimitiveTypeCode() == PrimitiveType.VOID);
		}

	}

	private static Type parseType(String typeString, IJavaProject javaProject, List<String> problemsCollector) {
		if ("".equals(typeString.trim())) //speed up for a common case //$NON-NLS-1$
			return null;
		if (! typeString.trim().equals(typeString))
			return null;

		StringBuilder cuBuff= new StringBuilder();
		cuBuff.append("interface A{"); //$NON-NLS-1$
		int offset= cuBuff.length();
		cuBuff.append(typeString).append(" m();}"); //$NON-NLS-1$

		ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
		p.setSource(cuBuff.toString().toCharArray());
		p.setProject(javaProject);
		CompilationUnit cu= (CompilationUnit) p.createAST(null);
		Selection selection= Selection.createFromStartLength(offset, typeString.length());
		SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
		cu.accept(analyzer);
		ASTNode selected= analyzer.getFirstSelectedNode();
		if (!(selected instanceof Type))
			return null;
		Type type= (Type)selected;
		if (MethodTypesSyntaxChecker.isVoidArrayType(type))
			return null;
		for (IProblem problem : ASTNodes.getProblems(type, ASTNodes.NODE_ONLY, ASTNodes.PROBLEMS)) {
			problemsCollector.add(problem.getMessage());
		}
		String typeNodeRange= cuBuff.substring(type.getStartPosition(), ASTNodes.getExclusiveEnd(type));
		if (typeString.equals(typeNodeRange))
			return type;
		else
			return null;
	}

	private static ITypeBinding handleBug84585(ITypeBinding typeBinding) {
		if (typeBinding != null
				&& typeBinding.isGenericType()
				&& ! typeBinding.isRawType()
				&& ! typeBinding.isParameterizedType() //see bug 84585
				) {
			return null;
		} else {
			return typeBinding;
		}
	}

	public static RefactoringStatus[] checkAndResolveMethodTypes(IMethod method, StubTypeContext stubTypeContext, List<ParameterInfo> parameterInfos, ReturnTypeInfo returnTypeInfo) throws CoreException {
		MethodTypesChecker checker= new MethodTypesChecker(method, stubTypeContext, parameterInfos, returnTypeInfo);
		return checker.checkAndResolveMethodTypes();
	}

	public static RefactoringStatus[] checkMethodTypesSyntax(IMethod method, List<ParameterInfo> parameterInfos, ReturnTypeInfo returnTypeInfo) {
		MethodTypesSyntaxChecker checker= new MethodTypesSyntaxChecker(method, parameterInfos, returnTypeInfo);
		return checker.checkSyntax();
	}

	public static RefactoringStatus checkParameterTypeSyntax(String type, IJavaProject project) {
		String newTypeName= ParameterInfo.stripEllipsis(type.trim()).trim();
		String typeLabel= BasicElementLabels.getJavaElementName(type);

		if ("".equals(newTypeName.trim())){ //$NON-NLS-1$
			String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_parameter_type, typeLabel);
			return RefactoringStatus.createFatalErrorStatus(msg);
		}

		if (ParameterInfo.isVarargs(type) && ! JavaModelUtil.is50OrHigher(project)) {
			String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_no_vararg_below_50, typeLabel);
			return RefactoringStatus.createFatalErrorStatus(msg);
		}

		List<String> problemsCollector= new ArrayList<>(0);
		Type parsedType= parseType(newTypeName, project, problemsCollector);
		boolean valid= parsedType != null;
		if (valid && parsedType instanceof PrimitiveType)
			valid= ! PrimitiveType.VOID.equals(((PrimitiveType) parsedType).getPrimitiveTypeCode());
		if (! valid) {
			String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_invalid_type_name, BasicElementLabels.getJavaElementName(newTypeName));
			return RefactoringStatus.createFatalErrorStatus(msg);
		}
		if (problemsCollector.isEmpty())
			return null;

		RefactoringStatus result= new RefactoringStatus();
		for (String problem : problemsCollector) {
			String msg= Messages.format(RefactoringCoreMessages.TypeContextChecker_invalid_type_syntax,
					new String[]{BasicElementLabels.getJavaElementName(newTypeName), BasicElementLabels.getJavaElementName(problem)});
			result.addError(msg);
		}
		return result;
	}

	public static StubTypeContext createStubTypeContext(ICompilationUnit cu, CompilationUnit root, int focalPosition) throws CoreException {
		StringBuilder bufBefore= new StringBuilder();
		StringBuilder bufAfter= new StringBuilder();

		int introEnd= 0;
		PackageDeclaration pack= root.getPackage();
		if (pack != null)
			introEnd= pack.getStartPosition() + pack.getLength();
		List<ImportDeclaration> imports= root.imports();
		if (imports.size() > 0) {
			ImportDeclaration lastImport= imports.get(imports.size() - 1);
			introEnd= lastImport.getStartPosition() + lastImport.getLength();
		}
		bufBefore.append(cu.getBuffer().getText(0, introEnd));

		fillWithTypeStubs(bufBefore, bufAfter, focalPosition, root.types());
		bufBefore.append(' ');
		bufAfter.insert(0, ' ');
		return new StubTypeContext(cu, bufBefore.toString(), bufAfter.toString());
	}

	private static void fillWithTypeStubs(final StringBuilder bufBefore, final StringBuilder bufAfter, final int focalPosition, List<? extends BodyDeclaration> types) {
		StringBuilder buf;
		for (BodyDeclaration bodyDeclaration : types) {
			if (! (bodyDeclaration instanceof AbstractTypeDeclaration)) {
				//account for local classes:
				if (! (bodyDeclaration instanceof MethodDeclaration))
					continue;
				int bodyStart= bodyDeclaration.getStartPosition();
				int bodyEnd= bodyDeclaration.getStartPosition() + bodyDeclaration.getLength();
				if ((bodyStart >= focalPosition) || (focalPosition >= bodyEnd))
					continue;
				MethodDeclaration methodDeclaration= (MethodDeclaration) bodyDeclaration;
				buf= bufBefore;
				appendModifiers(buf, methodDeclaration.modifiers());
				appendTypeParameters(buf, methodDeclaration.typeParameters());
				buf.append(" void "); //$NON-NLS-1$
				buf.append(methodDeclaration.getName().getIdentifier());
				buf.append("(){\n"); //$NON-NLS-1$
				Block body= methodDeclaration.getBody();
				body.accept(new HierarchicalASTVisitor() {
					@Override
					public boolean visit(AbstractTypeDeclaration node) {
						fillWithTypeStubs(bufBefore, bufAfter, focalPosition, Collections.singletonList(node));
						return false;
					}
					@Override
					public boolean visit(ClassInstanceCreation node) {
						AnonymousClassDeclaration anonDecl= node.getAnonymousClassDeclaration();
						if (anonDecl == null)
							return true; // could be in CIC parameter list
						int anonStart= anonDecl.getStartPosition();
						int anonEnd= anonDecl.getStartPosition() + anonDecl.getLength();
						if ((anonStart >= focalPosition) || (focalPosition >= anonEnd))
							return false;
						bufBefore.append(" new "); //$NON-NLS-1$
						bufBefore.append(node.getType().toString());
						bufBefore.append("(){\n"); //$NON-NLS-1$
						fillWithTypeStubs(bufBefore, bufAfter, focalPosition, anonDecl.bodyDeclarations());
						bufAfter.append("};\n"); //$NON-NLS-1$
						return false;
					}
				});
				buf= bufAfter;
				buf.append("}\n"); //$NON-NLS-1$
				continue;
			}

			AbstractTypeDeclaration decl= (AbstractTypeDeclaration) bodyDeclaration;
			buf= decl.getStartPosition() < focalPosition ? bufBefore : bufAfter;
			appendModifiers(buf, decl.modifiers());

			if (decl instanceof TypeDeclaration) {
				TypeDeclaration type= (TypeDeclaration) decl;
				buf.append(type.isInterface() ? "interface " : "class "); //$NON-NLS-1$//$NON-NLS-2$
				buf.append(type.getName().getIdentifier());
				appendTypeParameters(buf, type.typeParameters());
				if (type.getSuperclassType() != null) {
					buf.append(" extends "); //$NON-NLS-1$
					buf.append(ASTNodes.asString(type.getSuperclassType()));
				}
				List<Type> superInterfaces= type.superInterfaceTypes();
				appendSuperInterfaces(buf, superInterfaces);

			} else if (decl instanceof AnnotationTypeDeclaration) {
				AnnotationTypeDeclaration annotation= (AnnotationTypeDeclaration) decl;
				buf.append("@interface "); //$NON-NLS-1$
				buf.append(annotation.getName().getIdentifier());

			} else if (decl instanceof EnumDeclaration) {
				EnumDeclaration enumDecl= (EnumDeclaration) decl;
				buf.append("enum "); //$NON-NLS-1$
				buf.append(enumDecl.getName().getIdentifier());
				List<Type> superInterfaces= enumDecl.superInterfaceTypes();
				appendSuperInterfaces(buf, superInterfaces);
			}

			buf.append("{\n"); //$NON-NLS-1$
			if (decl instanceof EnumDeclaration)
				buf.append(";\n"); //$NON-NLS-1$
			fillWithTypeStubs(bufBefore, bufAfter, focalPosition, decl.bodyDeclarations());
			buf= decl.getStartPosition() + decl.getLength() < focalPosition ? bufBefore : bufAfter;
			buf.append("}\n"); //$NON-NLS-1$
		}
	}

	private static void appendTypeParameters(StringBuilder buf, List<TypeParameter> typeParameters) {
		int typeParametersCount= typeParameters.size();
		if (typeParametersCount > 0) {
			buf.append('<');
			for (int i= 0; i < typeParametersCount; i++) {
				TypeParameter typeParameter= typeParameters.get(i);
				buf.append(ASTNodes.asString(typeParameter));
				if (i < typeParametersCount - 1)
					buf.append(',');
			}
			buf.append('>');
		}
	}

	private static void appendModifiers(StringBuilder buf, List<IExtendedModifier> modifiers) {
		for (IExtendedModifier extendedModifier : modifiers) {
			if (extendedModifier.isModifier()) {
				Modifier modifier= (Modifier) extendedModifier;
				buf.append(modifier.getKeyword().toString()).append(' ');
			}
		}
	}

	private static void appendSuperInterfaces(StringBuilder buf, List<Type> superInterfaces) {
		int superInterfaceCount= superInterfaces.size();
		if (superInterfaceCount > 0) {
			buf.append(" implements "); //$NON-NLS-1$
			for (int i= 0; i < superInterfaceCount; i++) {
				Type superInterface= superInterfaces.get(i);
				buf.append(ASTNodes.asString(superInterface));
				if (i < superInterfaceCount - 1)
					buf.append(',');
			}
		}
	}

	public static StubTypeContext createSuperInterfaceStubTypeContext(String typeName, IType enclosingType, IPackageFragment packageFragment) {
		return createSupertypeStubTypeContext(typeName, true, enclosingType, packageFragment);
	}

	public static StubTypeContext createSuperClassStubTypeContext(String typeName, IType enclosingType, IPackageFragment packageFragment) {
		return createSupertypeStubTypeContext(typeName, false, enclosingType, packageFragment);
	}

	private static StubTypeContext createSupertypeStubTypeContext(String typeName, boolean isInterface, IType enclosingType, IPackageFragment packageFragment) {
		StubTypeContext stubTypeContext;
		String prolog= "class " + typeName + (isInterface ? " implements " : " extends "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		String epilog= " {} "; //$NON-NLS-1$
		if (enclosingType != null) {
			try {
				ICompilationUnit cu= enclosingType.getCompilationUnit();
				ISourceRange typeSourceRange= enclosingType.getSourceRange();
				int focalPosition= typeSourceRange.getOffset() + typeSourceRange.getLength() - 1; // before closing brace

				ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
				parser.setSource(cu);
				parser.setFocalPosition(focalPosition);
				CompilationUnit compilationUnit= (CompilationUnit) parser.createAST(null);

				stubTypeContext= createStubTypeContext(cu, compilationUnit, focalPosition);
				stubTypeContext= new StubTypeContext(stubTypeContext.getCuHandle(),
						stubTypeContext.getBeforeString() + prolog,
						epilog + stubTypeContext.getAfterString());
			} catch (CoreException e) {
				JavaPlugin.log(e);
				stubTypeContext= new StubTypeContext(null, null, null);
			}

		} else if (packageFragment != null) {
			ICompilationUnit cu= packageFragment.getCompilationUnit(JavaTypeCompletionProcessor.DUMMY_CU_NAME);
			stubTypeContext= new StubTypeContext(cu, "package " + packageFragment.getElementName() + ";" + prolog, epilog);  //$NON-NLS-1$//$NON-NLS-2$

		} else {
			stubTypeContext= new StubTypeContext(null, null, null);
		}
		return stubTypeContext;
	}

	public static StubTypeContext createAnnotationStubTypeContext(/*@NonNull*/ IProject project) {
		try {
			for (IPackageFragmentRoot root : JavaCore.create(project).getPackageFragmentRoots()) {
				if (!root.isReadOnly()) {
					IPackageFragment packageFragment= root.getPackageFragment(""); //$NON-NLS-1$
					String prolog= "abstract class __X__ {\n\tabstract @"; //$NON-NLS-1$
					String epilog= " __X__ dummy();\n} "; //$NON-NLS-1$
					ICompilationUnit cu= packageFragment.getCompilationUnit(JavaTypeCompletionProcessor.DUMMY_CU_NAME);
					return new StubTypeContext(cu, prolog, epilog);
				}
			}
		} catch (JavaModelException e) {
			// fall through
		}
		return new StubTypeContext(null, null, null);
	}

	public static Type parseSuperClass(String superClass) {
		return parseSuperType(superClass, false);
	}

	public static Type parseSuperInterface(String superInterface) {
		return parseSuperType(superInterface, true);
	}

	private static Type parseSuperType(String superType, boolean isInterface) {
		if (! superType.trim().equals(superType)) {
			return null;
		}

		StringBuilder cuBuff= new StringBuilder();
		if (isInterface)
			cuBuff.append("class __X__ implements "); //$NON-NLS-1$
		else
			cuBuff.append("class __X__ extends "); //$NON-NLS-1$
		int offset= cuBuff.length();
		cuBuff.append(superType).append(" {}"); //$NON-NLS-1$

		ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
		p.setSource(cuBuff.toString().toCharArray());
		Map<String, String> options= new HashMap<>();
		JavaModelUtil.setComplianceOptions(options, JavaModelUtil.VERSION_LATEST);
		p.setCompilerOptions(options);
		CompilationUnit cu= (CompilationUnit) p.createAST(null);
		ASTNode selected= NodeFinder.perform(cu, offset, superType.length());
		if (selected instanceof Name)
			selected= selected.getParent();
		if (selected.getStartPosition() != offset
				|| selected.getLength() != superType.length()
				|| ! (selected instanceof Type)
				|| selected instanceof PrimitiveType) {
			return null;
		}
		Type type= (Type) selected;

		String typeNodeRange= cuBuff.substring(type.getStartPosition(), ASTNodes.getExclusiveEnd(type));
		if (! superType.equals(typeNodeRange)){
			return null;
		}
		return type;
	}

	public static ITypeBinding resolveSuperClass(String superclass, IType typeHandle, StubTypeContext superClassContext) {
		StringBuilder cuString= new StringBuilder();
		cuString.append(superClassContext.getBeforeString());
		cuString.append(superclass);
		cuString.append(superClassContext.getAfterString());

		try {
			ICompilationUnit wc= typeHandle.getCompilationUnit().getWorkingCopy(new WorkingCopyOwner() {/*subclass*/}, new NullProgressMonitor());
			try {
				wc.getBuffer().setContents(cuString.toString());
				CompilationUnit compilationUnit= new RefactoringASTParser(IASTSharedValues.SHARED_AST_LEVEL).parse(wc, true);
				ASTNode type= NodeFinder.perform(compilationUnit, superClassContext.getBeforeString().length(), superclass.length());
				if (type instanceof Type) {
					return handleBug84585(((Type) type).resolveBinding());
				} else if (type instanceof Name) {
					ASTNode parent= type.getParent();
					if (parent instanceof Type)
						return handleBug84585(((Type) parent).resolveBinding());
				}
				throw new IllegalStateException();
			} finally {
				wc.discardWorkingCopy();
			}
		} catch (JavaModelException e) {
			return null;
		}
	}

	public static ITypeBinding[] resolveSuperInterfaces(String[] interfaces, IType typeHandle, StubTypeContext superInterfaceContext) {
		ITypeBinding[] result= new ITypeBinding[interfaces.length];

		int[] interfaceOffsets= new int[interfaces.length];
		StringBuilder cuString= new StringBuilder();
		cuString.append(superInterfaceContext.getBeforeString());
		int last= interfaces.length - 1;
		for (int i= 0; i <= last; i++) {
			interfaceOffsets[i]= cuString.length();
			cuString.append(interfaces[i]);
			if (i != last)
				cuString.append(", "); //$NON-NLS-1$
		}
		cuString.append(superInterfaceContext.getAfterString());

		try {
			ICompilationUnit wc= typeHandle.getCompilationUnit().getWorkingCopy(new WorkingCopyOwner() {/*subclass*/}, new NullProgressMonitor());
			try {
				wc.getBuffer().setContents(cuString.toString());
				CompilationUnit compilationUnit= new RefactoringASTParser(IASTSharedValues.SHARED_AST_LEVEL).parse(wc, true);
				for (int i= 0; i <= last; i++) {
					ASTNode type= NodeFinder.perform(compilationUnit, interfaceOffsets[i], interfaces[i].length());
					if (type instanceof Type) {
						result[i]= handleBug84585(((Type) type).resolveBinding());
					} else if (type instanceof Name) {
						ASTNode parent= type.getParent();
						if (parent instanceof Type) {
							result[i]= handleBug84585(((Type) parent).resolveBinding());
						} else {
							throw new IllegalStateException();
						}
					} else {
						throw new IllegalStateException();
					}
				}
			} finally {
				wc.discardWorkingCopy();
			}
		} catch (JavaModelException e) {
			// won't happen
		}
		return result;
	}

	private TypeContextChecker() {
	}
}
