<commit_before>package anatlyzer.atl.editor.quickfix.errors;

import java.util.function.Supplier;

import org.eclipse.core.resources.IMarker;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.IDocument;

import anatlyzer.atl.errors.atl_error.AccessToUndefinedValue;
import anatlyzer.atl.quickfixast.ASTUtils;
import anatlyzer.atl.quickfixast.InDocumentSerializer;
import anatlyzer.atl.quickfixast.QuickfixApplication;
import anatlyzer.atl.types.Type;
import anatlyzer.atlext.OCL.OCLFactory;
import anatlyzer.atlext.OCL.OclExpression;
import anatlyzer.atlext.OCL.PropertyCallExp;

/**
 * This quickfix proposes enclosing the problem in an "if" expression checking the
 * expression "not obj.optionalProperty.oclIsUndefined()".
 * 
 * The quickfix tries to generate a reasonable default for the false branch.
 * 
 * @qfxName  Surround with 'if' expression
 * @qfxError {@link anatlyzer.atl.errors.atl_error.AccessToUndefinedValue}
 * 
 * @author jesusc
 */
public class AccessToUndefinedValue_AddIf extends RuleGeneratingQuickFix {

	
	@Override public boolean isApplicable(IMarker marker) {
		return checkProblemType(marker, AccessToUndefinedValue.class);
	}

	@Override public void resetCache() {};

	@Override public void apply(IDocument document) {
	
		QuickfixApplication qfa = getQuickfixApplication();
		new InDocumentSerializer(qfa, document).serialize();
	}

	@Override public String getDisplayString() {
		return "Add surrounding if";
	}

	@Override public QuickfixApplication getQuickfixApplication() {
		PropertyCallExp pce = (PropertyCallExp) this.getProblematicElement();

		Supplier<OclExpression> createCheck = ASTUtils.createOclIsUndefinedCheck(pce.getSource());
	
		// Find the root of the expression
		OclExpression expRoot = null;
		EObject current = pce;
		do {
			expRoot = (OclExpression) current;
			current = current.eContainer();
		} while ( current instanceof OclExpression );
		
		final OclExpression fexpRoot = expRoot;
		final Type type = expRoot.getInferredType();
		QuickfixApplication qfa = new QuickfixApplication(this);
		qfa.change(expRoot, OCLFactory.eINSTANCE::createIfExp, (original, ifexp, trace) -> {
			ifexp.setCondition( createCheck.get() );
			ifexp.setThenExpression(fexpRoot);
			ifexp.setElseExpression(ASTUtils.defaultValue(type));
		});
		
		return qfa;
	}

}<commit_msg>* Fixed bug "add if" quickfix due to not checking that the if condition sometimes must be generated within an iterator<commit_after>package anatlyzer.atl.editor.quickfix.errors;

import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import org.eclipse.core.resources.IMarker;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.IDocument;

import anatlyzer.atl.errors.atl_error.AccessToUndefinedValue;
import anatlyzer.atl.quickfixast.ASTUtils;
import anatlyzer.atl.quickfixast.InDocumentSerializer;
import anatlyzer.atl.quickfixast.QuickfixApplication;
import anatlyzer.atl.types.Type;
import anatlyzer.atl.util.ATLUtils;
import anatlyzer.atlext.OCL.LoopExp;
import anatlyzer.atlext.OCL.OCLFactory;
import anatlyzer.atlext.OCL.OclExpression;
import anatlyzer.atlext.OCL.PropertyCallExp;
import anatlyzer.atlext.OCL.VariableDeclaration;
import anatlyzer.atlext.OCL.VariableExp;

/**
 * This quickfix proposes enclosing the problem in an "if" expression checking the
 * expression "not obj.optionalProperty.oclIsUndefined()".
 * 
 * The quickfix tries to generate a reasonable default for the false branch.
 * 
 * @qfxName  Surround with 'if' expression
 * @qfxError {@link anatlyzer.atl.errors.atl_error.AccessToUndefinedValue}
 * 
 * @author jesusc
 */
public class AccessToUndefinedValue_AddIf extends RuleGeneratingQuickFix {

	
	@Override public boolean isApplicable(IMarker marker) {
		return checkProblemType(marker, AccessToUndefinedValue.class);
	}

	@Override public void resetCache() {};

	@Override public void apply(IDocument document) {
	
		QuickfixApplication qfa = getQuickfixApplication();
		new InDocumentSerializer(qfa, document).serialize();
	}

	@Override public String getDisplayString() {
		return "Add surrounding if";
	}

	@Override public QuickfixApplication getQuickfixApplication() {
		PropertyCallExp pce = (PropertyCallExp) this.getProblematicElement();

		Supplier<OclExpression> createCheck = ASTUtils.createOclIsUndefinedCheck(pce.getSource());
	
		Set<VariableDeclaration> usedVarSet = ATLUtils.findAllVarExp(pce.getSource()).stream().map(v -> v.getReferredVariable()).collect(Collectors.toSet());		

		// Find the root of the expression
		OclExpression expRoot = null;
		EObject current = pce;
		do {
			expRoot = (OclExpression) current;
			current = current.eContainer();
			
			if ( current instanceof LoopExp ) {
				LoopExp loop = (LoopExp) current;
				if ( usedVarSet.contains( loop.getIterators().get(0)) )
					break;				
			}			
		} while ( current instanceof OclExpression );
		
		final OclExpression fexpRoot = expRoot;
		final Type type = expRoot.getInferredType();
		QuickfixApplication qfa = new QuickfixApplication(this);
		qfa.change(expRoot, OCLFactory.eINSTANCE::createIfExp, (original, ifexp, trace) -> {
			ifexp.setCondition( createCheck.get() );
			ifexp.setThenExpression(fexpRoot);
			ifexp.setElseExpression(ASTUtils.defaultValue(type));
		});
		
		return qfa;
	}

}
{'fraction_non_alphanumeric': 0.09919520868425978, 'fraction_numerical': 0.00018716077110237696, 'mean_word_length': 5.309327036599764, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1095712', 'n_tokens_mistral': 1806, 'n_tokens_neox': 1654, 'n_words': 360}