<commit_before>package com.redhat.ceylon.compiler.analyzer;

import com.redhat.ceylon.compiler.model.Typed;
import com.redhat.ceylon.compiler.tree.Tree;
import com.redhat.ceylon.compiler.tree.Visitor;

public class DefiniteAssignmentVisitor extends Visitor {
    
    Typed declaration;
    boolean definitelyAssigned = false;
    boolean possiblyAssigned = false;
        
    public DefiniteAssignmentVisitor(Typed declaration) {
        this.declaration = declaration;
    }
    
    @Override
    public void visit(Tree.AnnotationList that) {}
    
    @Override
    public void visit(Tree.Member that) {
        if (!definitelyAssigned && Util.getDeclaration(that)==declaration) {
            throw new RuntimeException("Not definitely assigned: " + 
                    that.getIdentifier().getText());
        }
    }
    
    @Override
    public void visit(Tree.SpecifierStatement that) {
        if (possiblyAssigned) {
            throw new RuntimeException("Not definitely unassigned: " + 
                    that.getMember().getIdentifier().getText());
        }
        if (Util.getDeclaration(that.getMember())==declaration) {
            definitelyAssigned=true;
            possiblyAssigned=true;
        }
        super.visit(that);
    }
    
    @Override
    public void visit(Tree.Declaration that) {
        //TODO: I think this stuff is unnecessary
        //      what we really should be checking 
        //      is that the nested dec doesn't try
        //      to assign it at all!
        Boolean o = definitelyAssigned;
        Boolean p = possiblyAssigned;
        super.visit(that);
        definitelyAssigned = o;
        possiblyAssigned = p;
    }
    
    @Override
    public void visit(Tree.IfStatement that) {
        boolean o = definitelyAssigned;
        boolean p = possiblyAssigned;
        super.visit(that.getIfClause());
        boolean definitelyAssignedByIfClause = definitelyAssigned;
        boolean possiblyAssignedByIfClause = possiblyAssigned;
        definitelyAssigned = o;
        possiblyAssigned = p;
        if (that.getElseClause()!=null)
            super.visit(that.getElseClause());
        boolean definitelyAssignedByElseClause = definitelyAssigned;
        boolean possiblyAssignedByElseClause = possiblyAssigned;
        definitelyAssigned = o || (definitelyAssignedByIfClause && definitelyAssignedByElseClause);
        possiblyAssigned = o || possiblyAssignedByIfClause || possiblyAssignedByElseClause;
    }
    
    @Override
    public void visit(Tree.SwitchStatement that) {
        //TODO!!!
    }
    
    @Override
    public void visit(Tree.WhileClause that) {
        Boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }
    
    //Note: we do not need DoClause, here since it 
    //is always executed at least once!

    @Override
    public void visit(Tree.ForStatement that) {
        boolean o = definitelyAssigned;
        boolean p = possiblyAssigned;
        super.visit(that.getForClause());
        boolean definitelyAssignedByForClause = definitelyAssigned;
        boolean possiblyAssignedByForClause = possiblyAssigned;
        definitelyAssigned = o;
        possiblyAssigned = p;
        if (that.getFailClause()!=null)
            super.visit(that.getFailClause());
        boolean definitelyAssignedByFailClause = definitelyAssigned;
        boolean possiblyAssignedByFailClause = possiblyAssigned;
        definitelyAssigned = o || (definitelyAssignedByForClause && definitelyAssignedByFailClause);
        possiblyAssigned = o || possiblyAssignedByForClause || possiblyAssignedByFailClause;
    }
    

    @Override
    public void visit(Tree.FailClause that) {
        Boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }

    @Override
    public void visit(Tree.TryClause that) {
        Boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }

    @Override
    public void visit(Tree.CatchClause that) {
        Boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }
    
    @Override
    public void visit(Tree.FinallyClause that) {
        Boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }

    /**
     * Suppress navigation to members
     */
    @Override
    public void visit(Tree.MemberExpression that) {
        that.getPrimary().visit(this);            
    }
    
}<commit_msg>improve definite assignment validation<commit_after>package com.redhat.ceylon.compiler.analyzer;

import com.redhat.ceylon.compiler.model.Typed;
import com.redhat.ceylon.compiler.tree.Tree;
import com.redhat.ceylon.compiler.tree.Tree.This;
import com.redhat.ceylon.compiler.tree.Visitor;

public class DefiniteAssignmentVisitor extends Visitor {
    
    Typed declaration;
    
    boolean definitelyAssigned = false;
    boolean possiblyAssigned = false;
    boolean cannotAssign = true;
    boolean declared = false;
        
    public DefiniteAssignmentVisitor(Typed declaration) {
        this.declaration = declaration;
    }
    
    @Override
    public void visit(Tree.AnnotationList that) {}
    
    @Override
    public void visit(Tree.Member that) {
        if (Util.getDeclaration(that)==declaration) {
            if (!declared) {
               throw new RuntimeException("Not yet declared: " + 
                        that.getIdentifier().getText());
            }
            if (!definitelyAssigned) {
                throw new RuntimeException("Not definitely assigned: " + 
                        that.getIdentifier().getText());
            }
        }
    }
    
    @Override
    public void visit(Tree.SpecifierStatement that) {
        if (Util.getDeclaration(that.getMember())==declaration) {
            if (!declared) {
                throw new RuntimeException("Not yet declared: " + 
                        that.getMember().getIdentifier().getText());
            }
            if (possiblyAssigned) {
                throw new RuntimeException("Not definitely unassigned: " + 
                        that.getMember().getIdentifier().getText());
            }
            if (cannotAssign) {
                throw new RuntimeException("Cannot assign from here: " + 
                        that.getMember().getIdentifier().getText());
            }
            definitelyAssigned=true;
            possiblyAssigned=true;
        }
        super.visit(that);
    }
    
    @Override
    public void visit(Tree.Declaration that) {
        if (that.getModelNode()==declaration) {
            super.visit(that);
            declared = true;
            cannotAssign = false;
        }
        else {
            boolean c = cannotAssign;
            cannotAssign=true;
            super.visit(that);
            cannotAssign = c;
        }
    }
    
    @Override
    public void visit(Tree.IfStatement that) {
        boolean o = definitelyAssigned;
        boolean p = possiblyAssigned;
        super.visit(that.getIfClause());
        boolean definitelyAssignedByIfClause = definitelyAssigned;
        boolean possiblyAssignedByIfClause = possiblyAssigned;
        definitelyAssigned = o;
        possiblyAssigned = p;
        if (that.getElseClause()!=null)
            super.visit(that.getElseClause());
        boolean definitelyAssignedByElseClause = definitelyAssigned;
        boolean possiblyAssignedByElseClause = possiblyAssigned;
        definitelyAssigned = o || (definitelyAssignedByIfClause && definitelyAssignedByElseClause);
        possiblyAssigned = o || possiblyAssignedByIfClause || possiblyAssignedByElseClause;
    }
    
    @Override
    public void visit(Tree.SwitchStatement that) {
        //TODO!!!
    }
    
    @Override
    public void visit(Tree.WhileClause that) {
        boolean c = cannotAssign;
        cannotAssign=true;
        super.visit(that);
        cannotAssign = c;
    }
    
    @Override
    public void visit(Tree.DoClause that) {
        boolean c = cannotAssign;
        cannotAssign=true;
        super.visit(that);
        cannotAssign = c;
    }

    @Override
    public void visit(Tree.ForStatement that) {
        boolean o = definitelyAssigned;
        boolean c = cannotAssign;
        cannotAssign = true;
        super.visit(that.getForClause());
        cannotAssign = c;
        if (that.getFailClause()!=null)
            super.visit(that.getFailClause());
        definitelyAssigned = o;
    }
    

    @Override
    public void visit(Tree.FailClause that) {
        boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }

    @Override
    public void visit(Tree.TryClause that) {
        boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }

    @Override
    public void visit(Tree.CatchClause that) {
        boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }
    
    @Override
    public void visit(Tree.FinallyClause that) {
        boolean o = definitelyAssigned;
        super.visit(that);
        definitelyAssigned = o;
    }

    /**
     * Suppress navigation to members
     */
    @Override
    public void visit(Tree.MemberExpression that) {
        if (that.getPrimary() instanceof This) {
            super.visit(that);
        }
        else {
            that.getPrimary().visit(this);
        }
    }
    
}
{'fraction_non_alphanumeric': 0.08735098639096951, 'fraction_numerical': 0.0, 'mean_word_length': 2.191919191919192, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4265368', 'n_tokens_mistral': 2483, 'n_tokens_neox': 2502, 'n_words': 538}