/**
* Copyright (C) 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mujava.op.util;
import java.io.*;
import java.util.*;
import openjava.mop.*;
import openjava.ptree.*;
/**
* <p>Description: </p>
* @author Yu-Seung Ma
* @version 1.0
*/
public class ScopeHandlingMutantCodeWriter extends MutantCodeWriter
{
private Stack env_nest = new Stack();
private Environment env;
public ScopeHandlingMutantCodeWriter(Environment base_env, PrintWriter out)
{
super(out);
env = base_env;
}
public ScopeHandlingMutantCodeWriter( Environment base_env, String file_name, PrintWriter out )
{
super(file_name,out);
env = base_env;
}
protected final void pushClosedEnvironment() {
env_nest.push( getEnvironment() );
setEnvironment( new ClosedEnvironment( getEnvironment() ) );
}
protected final void push( Environment env ) {
env_nest.push( getEnvironment() );
setEnvironment( env );
}
protected final void pop() {
setEnvironment( (Environment) env_nest.pop() );
}
protected Environment getEnvironment() {
return env;
}
protected void setEnvironment( Environment env ) {
this.env = env;
}
/* compilation unit */
public void evaluateDown(CompilationUnit ptree)
throws ParseTreeException
{
ClassDeclaration pubclazz = ptree.getPublicClass();
String name = (pubclazz != null) ? pubclazz.getName()
: "<no public class>";
FileEnvironment fenv
= new FileEnvironment(getEnvironment(), ptree, name);
push( fenv );
}
/* class declaration */
public void evaluateDown( ClassDeclaration ptree )
throws ParseTreeException
{
/* records this class */
if (getEnvironment() instanceof ClosedEnvironment) {
recordLocalClass(ptree);
}
/* creates a new class environment */
ClassEnvironment env
= new ClassEnvironment(getEnvironment(), ptree.getName());
MemberDeclarationList mdecls = ptree.getBody();
for (int i = 0; i < mdecls.size(); ++i) {
MemberDeclaration m = mdecls.get(i);
if (! (m instanceof ClassDeclaration)) continue;
ClassDeclaration inner = (ClassDeclaration) m;
env.recordMemberClass(inner.getName());
}
push(env);
}
public void evaluateDown() throws ParseTreeException
{
pushClosedEnvironment();
}
public void evaluateUp() throws ParseTreeException
{
pop();
}
private void recordLocalClass(ClassDeclaration ptree) {
String classname = ptree.getName();
Environment outer_env = getEnvironment();
String qname = outer_env.toQualifiedName(classname);
if (outer_env.lookupClass(qname) != null) return;
try {
OJClass out_clazz
= outer_env.lookupClass(outer_env.currentClassName());
/***** this will be recorded in global env */
//OJClass clazz = OJClass.forParseTree(outer_env, out_clazz, ptree);
OJClass clazz = new OJClass(outer_env, out_clazz, ptree);
outer_env.record(classname, clazz);
} catch (Exception ex) {
System.err.println("unknown error: " + ex);
return;
}
}
public void visit( CompilationUnit p ) throws ParseTreeException {
this.evaluateDown(p);
super.visit(p);
this.evaluateUp();
}
public void visit( ConstructorDeclaration p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( MemberInitializer p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( SwitchStatement p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( SynchronizedStatement p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( TryStatement p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit(Parameter p) throws openjava.ptree.ParseTreeException
{
bindParameter( p, getEnvironment() );
super.visit(p);
}
public OJClass getType( Expression p ) throws ParseTreeException {
OJClass result = null;
try {
result = p.getType( getEnvironment() );
} catch ( Exception e ) {
e.printStackTrace();
throw new ParseTreeException( e );
}
if (result == null) {
System.err.println("cannot resolve the type of expression");
System.err.println(p.getClass() + " : " + p);
System.err.println(getEnvironment());
/*****DebugOut.println(getEnvironment().toString());*/
if (p instanceof ArrayAccess) {
ArrayAccess aaexpr = (ArrayAccess) p;
Expression refexpr = aaexpr.getReferenceExpr();
OJClass refexprtype = null;
OJClass comptype = null;
try {
refexprtype = refexpr.getType(getEnvironment());
comptype = refexprtype.getComponentType();
} catch (Exception ex) {}
System.err.println(refexpr + " : " + refexprtype + " : " +
comptype);
}
}
return result;
}
public OJClass getSelfType() throws ParseTreeException {
OJClass result;
try {
Environment env = getEnvironment();
String selfname = env.currentClassName();
result = env.lookupClass(selfname);
} catch (Exception ex) {
throw new ParseTreeException(ex);
}
return result;
}
public OJClass getType( TypeName typename ) throws ParseTreeException {
OJClass result = null;
try {
Environment env = getEnvironment();
String qname = env.toQualifiedName(typename.toString());
result = env.lookupClass(qname);
} catch (Exception ex) {
throw new ParseTreeException(ex);
}
if (result == null) {
System.err.println("unknown type for a type name : " + typename);
}
return result;
}
protected OJClass computeRefType( TypeName typename, Expression expr )
throws ParseTreeException
{
if (typename != null) return getType( typename );
if (expr != null) return getType( expr );
return getSelfType();
}
protected static void bindLocalVariable( VariableDeclaration var_decl,
Environment env )
{
String type = var_decl.getTypeSpecifier().toString();
String name = var_decl.getVariable();
bindName( env, type, name );
}
private static void bindName( Environment env, String type, String name ) {
String qtypename = env.toQualifiedName( type );
try {
OJClass clazz = env.lookupClass( qtypename );
if (clazz == null) clazz = OJClass.forName( qtypename );
env.bindVariable( name, clazz );
} catch ( OJClassNotFoundException e ) {
System.err.println( "VariableBinder.bindName() " +
e.toString() + " : " + qtypename );
System.err.println( env );
}
}
private static void bindParameter( Parameter param, Environment env ) {
String type = param.getTypeSpecifier().toString();
String name = param.getVariable();
bindName( env, type, name );
}
private static void bindForInit( TypeName tspec,
VariableDeclarator[] vdecls,
Environment env ) {
for (int i = 0; i < vdecls.length; ++i) {
String type = tspec.toString() + vdecls[i].dimensionString();
String name = vdecls[i].getVariable();
bindName( env, type, name );
}
}
public void visit( ClassDeclaration p ) throws ParseTreeException {
this.evaluateDown( p );
super.visit(p);
this.evaluateUp();
}
public void visit( Block p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( DoWhileStatement p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( ForStatement p ) throws ParseTreeException {
System.out.println("mujava-scopehandingmutantcodewriter=forstatemnt");
this.evaluateDown();
TypeName tspec = p.getInitDeclType();
if (tspec != null){
VariableDeclarator[] vdecls = p.getInitDecls();
bindForInit( tspec, vdecls, getEnvironment() );
}
super.visit(p);
this.evaluateUp();
}
public void visit( IfStatement p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( MethodDeclaration p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit( WhileStatement p ) throws ParseTreeException {
this.evaluateDown();
super.visit(p);
this.evaluateUp();
}
public void visit(VariableDeclaration p) throws openjava.ptree.ParseTreeException
{
bindLocalVariable( p, getEnvironment() );
super.visit(p);
}
}