<commit_before>package com.redhat.ceylon.eclipse.core.debug.model;

import java.util.List;

import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.internal.debug.core.model.JDIStackFrame;
import org.eclipse.jdt.internal.debug.core.model.PatchedForCeylonJDIThread;

import com.redhat.ceylon.eclipse.core.debug.DebugUtils;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.request.StepRequest;

public class CeylonJDIThread extends PatchedForCeylonJDIThread {
    public CeylonJDIThread(CeylonJDIDebugTarget debugTarget, ThreadReference reference) {
        super(debugTarget, reference);
    }

    private IJavaStackFrame[] startStackFrame = new IJavaStackFrame[1];
    
    @Override
    protected synchronized List<IJavaStackFrame> computeStackFrames(
            boolean refreshChildren) throws DebugException {
        List<IJavaStackFrame> stackFrames = super.computeStackFrames(refreshChildren);
        if (refreshChildren) {
            synchronized (startStackFrame) {
                try {
                    CeylonJDIDebugTarget target = getDebugTarget();
                    if (target.isMainThread(this)) {
                        for (int i=0; i<stackFrames.size(); i++) {
                            JDIStackFrame frame = (JDIStackFrame)stackFrames.get(i);
                            Location location = frame.getUnderlyingMethod().location();
                            String locationString = new StringBuilder()
                                                .append(location.declaringType().name())
                                                .append('/')
                                                .append(location.method().name())
                                                .toString();
                            if (locationString.equals(target.getStartLocation())) {
                                startStackFrame[0] = frame;
                                break;
                            }
                        }
                    }
                } catch(Throwable t) {
                    t.printStackTrace();
                    startStackFrame[0] = null;
                }
            }
        }
        return stackFrames;
    }

    @Override
    public CeylonJDIDebugTarget getDebugTarget() {
        return (CeylonJDIDebugTarget) super.getDebugTarget();
    }
    
    public boolean isBeforeStart(IJavaStackFrame aFrame) {
        CeylonJDIDebugTarget target = getDebugTarget();
        if (target.isMainThread(this)) {
            try {
                List<IJavaStackFrame> stackFrames = computeStackFrames();
                synchronized (startStackFrame) {
                    if (startStackFrame[0] != null) {
                        for (int i=stackFrames.size() - 1; i >= 0; i--) {
                            if (stackFrames.get(i).equals(startStackFrame[0])) {
                                return false;
                            }
                            if (stackFrames.get(i).equals(aFrame)) {
                                return true;
                            }
                        }
                        return true;
                    }
                }
                
            } catch (DebugException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    @Override
    public synchronized IStackFrame getTopStackFrame() throws DebugException {
        IStackFrame topStackFrame = super.getTopStackFrame();
        return topStackFrame;
    }
    
    boolean steppingThroughLocation = false;
    
    private boolean locationIsFilteredForCeylon(Method method) {
        steppingThroughLocation = DebugUtils.isCeylonGeneratedMethodToStepThrough(method);
        return DebugUtils.isMethodFiltered(method);
    }
    
    private int changeSecondaryStepRequestKindForCeylon(int currentStepKind) throws DebugException {
        if (steppingThroughLocation) {
            steppingThroughLocation = false;
            return StepRequest.STEP_INTO;
        } else {
            return currentStepKind;
        }
    }

    @Override
    protected StepIntoHandler newStepIntoHandler() {
        return new StepIntoHandler() {
            @Override
            protected boolean locationIsFiltered(Method method) {
                return locationIsFilteredForCeylon(method);
            }
            @Override
            protected void createSecondaryStepRequest() throws DebugException {
                createSecondaryStepRequest(changeSecondaryStepRequestKindForCeylon(getStepKind()));
            }
        };
        
    }

    @Override
    protected StepOverHandler newStepOverHandler() {
        return new StepOverHandler() {
            @Override
            protected boolean locationIsFiltered(Method method) {
                return locationIsFilteredForCeylon(method);
            }
            @Override
            protected void createSecondaryStepRequest() throws DebugException {
                createSecondaryStepRequest(changeSecondaryStepRequestKindForCeylon(getStepKind()));
            }
        };
    }

    @Override
    protected StepReturnHandler newStepReturnHandler() {
        return new StepReturnHandler() {
            @Override
            protected boolean locationIsFiltered(Method method) {
                return locationIsFilteredForCeylon(method);
            }
            @Override
            protected void createSecondaryStepRequest() throws DebugException {
                createSecondaryStepRequest(changeSecondaryStepRequestKindForCeylon(getStepKind()));
            }
        };
    }
    
    
    protected boolean shouldDoStepReturn() throws DebugException {
        boolean shouldDoStepReturn = super.shouldDoStepReturn();
        if (shouldDoStepReturn) {
            try {
                StackFrame previousFrame = getUnderlyingThread().frame(1);
                if (DebugUtils.isMethodToStepThrough(previousFrame.location().method())) {
                    return false;
                }
            } catch (IncompatibleThreadStateException e) {
                e.printStackTrace();
            }
            return true;
        }
        return false;
    }
}<commit_msg>Subtle bugs when coming out from a stepped through location (were showed by the case of method with default parameters)<commit_after>package com.redhat.ceylon.eclipse.core.debug.model;

import java.util.List;

import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.internal.debug.core.model.JDIStackFrame;
import org.eclipse.jdt.internal.debug.core.model.PatchedForCeylonJDIThread;

import com.redhat.ceylon.eclipse.core.debug.DebugUtils;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.request.StepRequest;

public class CeylonJDIThread extends PatchedForCeylonJDIThread {
    public CeylonJDIThread(CeylonJDIDebugTarget debugTarget, ThreadReference reference) {
        super(debugTarget, reference);
    }

    private IJavaStackFrame[] startStackFrame = new IJavaStackFrame[1];
    
    @Override
    protected synchronized List<IJavaStackFrame> computeStackFrames(
            boolean refreshChildren) throws DebugException {
        List<IJavaStackFrame> stackFrames = super.computeStackFrames(refreshChildren);
        if (refreshChildren) {
            synchronized (startStackFrame) {
                try {
                    CeylonJDIDebugTarget target = getDebugTarget();
                    if (target.isMainThread(this)) {
                        for (int i=0; i<stackFrames.size(); i++) {
                            JDIStackFrame frame = (JDIStackFrame)stackFrames.get(i);
                            Location location = frame.getUnderlyingMethod().location();
                            String locationString = new StringBuilder()
                                                .append(location.declaringType().name())
                                                .append('/')
                                                .append(location.method().name())
                                                .toString();
                            if (locationString.equals(target.getStartLocation())) {
                                startStackFrame[0] = frame;
                                break;
                            }
                        }
                    }
                } catch(Throwable t) {
                    t.printStackTrace();
                    startStackFrame[0] = null;
                }
            }
        }
        return stackFrames;
    }

    @Override
    public CeylonJDIDebugTarget getDebugTarget() {
        return (CeylonJDIDebugTarget) super.getDebugTarget();
    }
    
    public boolean isBeforeStart(IJavaStackFrame aFrame) {
        CeylonJDIDebugTarget target = getDebugTarget();
        if (target.isMainThread(this)) {
            try {
                List<IJavaStackFrame> stackFrames = computeStackFrames();
                synchronized (startStackFrame) {
                    if (startStackFrame[0] != null) {
                        for (int i=stackFrames.size() - 1; i >= 0; i--) {
                            if (stackFrames.get(i).equals(startStackFrame[0])) {
                                return false;
                            }
                            if (stackFrames.get(i).equals(aFrame)) {
                                return true;
                            }
                        }
                        return true;
                    }
                }
                
            } catch (DebugException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    @Override
    public synchronized IStackFrame getTopStackFrame() throws DebugException {
        IStackFrame topStackFrame = super.getTopStackFrame();
        return topStackFrame;
    }
    
    boolean steppingThroughLocation = false;
    boolean originalLocationIsAnAncestor = false;
        
    private int changeSecondaryStepRequestKindForCeylon(int currentStepKind) throws DebugException {
        if (steppingThroughLocation) {
            steppingThroughLocation = false;
            return StepRequest.STEP_INTO;
        } else {
            return currentStepKind;
        }
    }

    @Override
    protected StepIntoHandler newStepIntoHandler() {
        return new StepIntoHandler() {
            @Override
            protected boolean locationIsFiltered(Method method) {
                return DebugUtils.isMethodFiltered(method);
            }
            @Override
            protected boolean locationShouldBeFiltered(Location location)
                    throws DebugException {
                storeAdditionalLocationData(location);
                return super.locationShouldBeFiltered(location);
            }
            @Override
            protected void createSecondaryStepRequest() throws DebugException {
                createSecondaryStepRequest(changeSecondaryStepRequestKindForCeylon(getStepKind()));
            }
        };
        
    }

    @Override
    protected StepOverHandler newStepOverHandler() {
        return new StepOverHandler() {
            @Override
            protected boolean locationIsFiltered(Method method) {
                return DebugUtils.isMethodFiltered(method);
            }
            @Override
            protected boolean locationShouldBeFiltered(Location location)
                    throws DebugException {
                storeAdditionalLocationData(location);
                return super.locationShouldBeFiltered(location);
            }
            @Override
            protected void createSecondaryStepRequest() throws DebugException {
                createSecondaryStepRequest(changeSecondaryStepRequestKindForCeylon(getStepKind()));
            }
        };
    }

    @Override
    protected StepReturnHandler newStepReturnHandler() {
        return new StepReturnHandler() {
            @Override
            protected boolean locationIsFiltered(Method method) {
                return DebugUtils.isMethodFiltered(method);
            }
            @Override
            protected boolean locationShouldBeFiltered(Location location)
                    throws DebugException {
                storeAdditionalLocationData(location);
                return super.locationShouldBeFiltered(location);
            }
            @Override
            protected void createSecondaryStepRequest() throws DebugException {
                createSecondaryStepRequest(changeSecondaryStepRequestKindForCeylon(getStepKind()));
            }
        };
    }
    
    
    protected boolean shouldDoStepReturn() throws DebugException {
        boolean shouldDoStepReturn = super.shouldDoStepReturn();
        if (shouldDoStepReturn) {
            try {
                StackFrame previousFrame = getUnderlyingThread().frame(1);
                if (DebugUtils.isMethodToStepThrough(previousFrame.location().method())) {
                    return false;
                }
            } catch (IncompatibleThreadStateException e) {
                e.printStackTrace();
            }
            return true;
        }
        return false;
    }
    
    @Override
    protected boolean shouldDoExtraStepInto(Location location)
            throws DebugException {
        return super.shouldDoExtraStepInto(location) && originalLocationIsAnAncestor;
    }

    public void storeAdditionalLocationData(Location location)
            throws DebugException {
        steppingThroughLocation = DebugUtils.isCeylonGeneratedMethodToStepThrough(location.method());
        if (getUnderlyingFrameCount() < getOriginalStepStackDepth()) {
            originalLocationIsAnAncestor = false;
        }
    }
    
    @Override
    protected void setOriginalStepLocation(Location location) {
        originalLocationIsAnAncestor = true;
        super.setOriginalStepLocation(location);
    }
}
{'fraction_non_alphanumeric': 0.07320125130344109, 'fraction_numerical': 0.001251303441084463, 'mean_word_length': 1.7522479433709586, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3962519', 'n_tokens_mistral': 3443, 'n_tokens_neox': 3254, 'n_words': 621}