📄 definiteassignment.jrag
字号:
/* * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered * by the modified BSD License. You should have received a copy of the * modified BSD license with this compiler. * * Copyright (c) 2005-2008, Torbjorn Ekman * All rights reserved. */aspect DefiniteAssignment { public void ASTNode.definiteAssignment() { } inh boolean Expr.isDest(); eq Program.getChild().isDest() = false; eq AssignSimpleExpr.getDest().isDest() = true; eq AssignExpr.getDest().isDest() = true; eq AssignExpr.getSource().isDest() = false; eq TypeDecl.getBodyDecl().isDest() = false; eq AbstractDot.getLeft().isDest() = false; eq ImportDecl.getAccess().isDest() = false; inh boolean Expr.isSource(); eq Program.getChild().isSource() = true; eq AssignSimpleExpr.getDest().isSource() = false; eq AssignExpr.getDest().isSource() = true; eq AssignExpr.getSource().isSource() = true; eq TypeDecl.getBodyDecl().isSource() = true; eq AbstractDot.getLeft().isSource() = true; eq ImportDecl.getAccess().isSource() = true; eq ArrayAccess.getExpr().isDest() = false; eq ArrayAccess.getExpr().isSource() = true; eq ArrayTypeWithSizeAccess.getExpr().isDest() = false; eq ArrayTypeWithSizeAccess.getExpr().isSource() = true; eq FieldDeclaration.getInit().isSource() = true; eq VariableDeclaration.getInit().isSource() = true; eq VariableDecl.getInit().isSource() = true; // is this needed? eq ArrayInit.getInit().isSource() = true; eq Unary.getOperand().isSource() = true; eq PostfixExpr.getOperand().isDest() = true; eq PreIncExpr.getOperand().isDest() = true; eq PreDecExpr.getOperand().isDest() = true; inh boolean Expr.isIncOrDec(); eq Program.getChild().isIncOrDec() = false; eq CompilationUnit.getTypeDecl().isIncOrDec() = false; eq Block.getStmt().isIncOrDec() = false; eq PostfixExpr.getOperand().isIncOrDec() = true; eq PreIncExpr.getOperand().isIncOrDec() = true; eq PreDecExpr.getOperand().isIncOrDec() = true; syn Variable Expr.varDecl() = null; eq AbstractDot.varDecl() = lastAccess().varDecl(); eq VarAccess.varDecl() = decl(); eq ParExpr.varDecl() = getExpr().varDecl(); public void PostfixExpr.definiteAssignment() { if(getOperand().isVariable()) { Variable v = getOperand().varDecl(); if(v != null && v.isFinal()) { error("++ and -- can not be applied to final variable " + v); } } } public void PreIncExpr.definiteAssignment() { if(getOperand().isVariable()) { Variable v = getOperand().varDecl(); if(v != null && v.isFinal()) { error("++ and -- can not be applied to final variable " + v); } } } public void PreDecExpr.definiteAssignment() { if(getOperand().isVariable()) { Variable v = getOperand().varDecl(); if(v != null && v.isFinal()) { error("++ and -- can not be applied to final variable " + v); } } } // final variables with a constant initializer are considered values and not variables syn boolean VariableDeclaration.isBlankFinal() = isFinal() && (!hasInit() || !getInit().isConstant()); syn boolean VariableDeclaration.isValue() = isFinal() && hasInit() && getInit().isConstant(); public void VarAccess.definiteAssignment() { if(isSource()) { if(decl() instanceof VariableDeclaration) { VariableDeclaration v = (VariableDeclaration)decl(); //System.err.println("Is " + v + " final? " + v.isFinal() + ", DAbefore: " + isDAbefore(v)); if(v.isValue()) { } else if(v.isBlankFinal()) { //if(!isDAbefore(v) && !v.hasInit() && !v.getInit().isConstant()) if(!isDAbefore(v)) error("Final variable " + v.name() + " is not assigned before used"); } else { //if(!v.hasInit() && !isDAbefore(v)) { if(!isDAbefore(v)) error("Local variable " + v.name() + " in not assigned before used"); } } else if(decl() instanceof FieldDeclaration && !isQualified()) { FieldDeclaration f = (FieldDeclaration)decl(); //if(f.isFinal() && f.isInstanceVariable() && !isDAbefore(f)) { //if(f.isFinal() && !isDAbefore(f) && (!f.hasInit() || !f.getInit().isConstant())) { //if(f.isFinal() && (!f.hasInit() || !f.getInit().isConstant()) && !isDAbefore(f)) { if(f.isFinal() && !f.hasInit() && !isDAbefore(f)) { error("Final field " + f + " is not assigned before used"); } } } if(isDest()) { Variable v = decl(); // Blank final field if(v.isFinal() && v.isBlank() && !hostType().instanceOf(v.hostType())) error("The final variable is not a blank final in this context, so it may not be assigned."); else if(v.isFinal() && isQualified() && (!qualifier().isThisAccess() || ((Access)qualifier()).isQualified())) error("the blank final field " + v.name() + " may only be assigned by simple name"); // local variable or parameter else if(v instanceof VariableDeclaration) { VariableDeclaration var = (VariableDeclaration)v; //System.out.println("### is variable"); if(!var.isValue() && var.getParent().getParent().getParent() instanceof SwitchStmt && var.isFinal()) { if(!isDUbefore(var)) error("Final variable " + var.name() + " may only be assigned once"); } else if(var.isValue()) { if(var.hasInit() || !isDUbefore(var)) error("Final variable " + var.name() + " may only be assigned once"); } else if(var.isBlankFinal()) { if(var.hasInit() || !isDUbefore(var)) error("Final variable " + var.name() + " may only be assigned once"); } if(var.isFinal() && (var.hasInit() || !isDUbefore(var))) { //if(var.isFinal() && ((var.hasInit() && var.getInit().isConstant()) || !isDUbefore(var))) { } } // field else if(v instanceof FieldDeclaration) { FieldDeclaration f = (FieldDeclaration)v; if(f.isFinal()) { if(f.hasInit()) error("initialized field " + f.name() + " can not be assigned"); else { BodyDecl bodyDecl = enclosingBodyDecl(); if(!(bodyDecl instanceof ConstructorDecl) && !(bodyDecl instanceof InstanceInitializer) && !(bodyDecl instanceof StaticInitializer) && !(bodyDecl instanceof FieldDeclaration)) error("final field " + f.name() + " may only be assigned in constructors and initializers"); else if(!isDUbefore(f)) error("Final field " + f.name() + " may only be assigned once"); } } } else if(v instanceof ParameterDeclaration) { ParameterDeclaration p = (ParameterDeclaration)v; // 8.4.1 if(p.isFinal()) { error("Final parameter " + p.name() + " may not be assigned"); } } } } public void FieldDeclaration.definiteAssignment() { super.definiteAssignment(); if(isBlank() && isFinal() && isClassVariable()) { boolean found = false; TypeDecl typeDecl = hostType(); for(int i = 0; i < typeDecl.getNumBodyDecl(); i++) { if(typeDecl.getBodyDecl(i) instanceof StaticInitializer) { StaticInitializer s = (StaticInitializer)typeDecl.getBodyDecl(i); if(s.isDAafter(this)) found = true; } else if(typeDecl.getBodyDecl(i) instanceof FieldDeclaration) { FieldDeclaration f = (FieldDeclaration)typeDecl.getBodyDecl(i); if(f.isStatic() && f.isDAafter(this)) found = true; } } if(!found) error("blank final class variable " + name() + " in " + hostType().typeName() + " is not definitely assigned in static initializer"); } if(isBlank() && isFinal() && isInstanceVariable()) { TypeDecl typeDecl = hostType(); boolean found = false; for(int i = 0; !found && i < typeDecl.getNumBodyDecl(); i++) { if(typeDecl.getBodyDecl(i) instanceof FieldDeclaration) { FieldDeclaration f = (FieldDeclaration)typeDecl.getBodyDecl(i); if(!f.isStatic() && f.isDAafter(this)) found = true; } else if(typeDecl.getBodyDecl(i) instanceof InstanceInitializer) { InstanceInitializer ii = (InstanceInitializer)typeDecl.getBodyDecl(i); if(ii.getBlock().isDAafter(this)) found = true; } } for(Iterator iter = typeDecl.constructors().iterator(); !found && iter.hasNext(); ) { ConstructorDecl c = (ConstructorDecl)iter.next(); if(!c.isDAafter(this)) { error("blank final instance variable " + name() + " in " + hostType().typeName() + " is not definitely assigned after " + c.signature()); } } } if(isBlank() && hostType().isInterfaceDecl()) { error("variable " + name() + " in " + hostType().typeName() + " which is an interface must have an initializer"); } }}aspect DA { syn lazy boolean ConditionalExpr.booleanOperator() = getTrueExpr().type().isBoolean() && getFalseExpr().type().isBoolean(); inh boolean Stmt.isDAbefore(Variable v); syn lazy boolean Stmt.isDAafter(Variable v); inh boolean Expr.isDAbefore(Variable v); syn boolean Expr.isDAafter(Variable v); syn lazy boolean Binary.isDAafter(Variable v); syn lazy boolean AbstractDot.isDAafter(Variable v); inh lazy boolean TypeDecl.isDAbefore(Variable v); inh lazy boolean BodyDecl.isDAbefore(Variable v); syn lazy boolean BodyDecl.isDAafter(Variable v) = true; eq TypeDecl.getBodyDecl().isDAbefore(Variable v) { BodyDecl b = getBodyDecl(childIndex); //if(b instanceof MethodDecl || b instanceof MemberTypeDecl) { if(!v.isInstanceVariable() && !v.isClassVariable()) { if(v.hostType() != this) return isDAbefore(v); return false; } if(b instanceof FieldDeclaration && !((FieldDeclaration)b).isStatic() && v.isClassVariable()) return true; if(b instanceof MethodDecl) { return true; } if(b instanceof MemberTypeDecl && v.isBlank() && v.isFinal() && v.hostType() == this) return true; if(v.isClassVariable() || v.isInstanceVariable()) { if(v.isFinal() && v.hostType() != this && instanceOf(v.hostType())) return true; int index = childIndex - 1; if(b instanceof ConstructorDecl) index = getNumBodyDecl() - 1; for(int i = index; i >= 0; i--) { b = getBodyDecl(i); if(b instanceof FieldDeclaration) { FieldDeclaration f = (FieldDeclaration)b; if((v.isClassVariable() && f.isStatic()) || (v.isInstanceVariable() && !f.isStatic())) { boolean c = f.isDAafter(v); //System.err.println("DefiniteAssignment: is " + v.name() + " DA after index " + i + ", " + f + ": " + c); return c; //return f.isDAafter(v); } } else if(b instanceof StaticInitializer && v.isClassVariable()) { StaticInitializer si = (StaticInitializer)b; return si.isDAafter(v); } else if(b instanceof InstanceInitializer && v.isInstanceVariable()) { InstanceInitializer ii = (InstanceInitializer)b; return ii.isDAafter(v); } } } return isDAbefore(v); } eq InstanceInitializer.isDAafter(Variable v) = getBlock().isDAafter(v); eq StaticInitializer.isDAafter(Variable v) = getBlock().isDAafter(v); eq ConstructorDecl.isDAafter(Variable v) = getBlock().isDAafter(v) && getBlock().checkReturnDA(v); eq ConstructorAccess.isDAafter(Variable v) = decl().isDAafter(v); eq SuperConstructorAccess.isDAafter(Variable v) = isDAbefore(v); eq ConstructorDecl.getBlock().isDAbefore(Variable v) = hasConstructorInvocation() ? getConstructorInvocation().isDAafter(v) : isDAbefore(v); syn lazy boolean Block.checkReturnDA(Variable v) { HashSet set = new HashSet(); collectBranches(set); for(Iterator iter = set.iterator(); iter.hasNext(); ) { Object o = iter.next(); if(o instanceof ReturnStmt) { ReturnStmt stmt = (ReturnStmt)o; if(!stmt.isDAafterReachedFinallyBlocks(v)) return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -