summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/SourcedAst.java
blob: 52a345340e754ca99124940111620e571c1b48c2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*******************************************************************************
 * Copyright (c) 2014 Jeff Martin.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Jeff Martin - initial API and implementation
 ******************************************************************************/
package cuchaz.enigma.analysis;

import java.io.IOException;
import java.util.HashMap;

import javassist.bytecode.Descriptor;

import com.google.common.collect.Maps;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.Trees;

public class SourcedAst
{
	private CompilationUnitTree m_tree;
	private Trees m_trees;
	private SourcePositions m_positions;
	private HashMap<String,String> m_classNameIndex;
	
	public SourcedAst( CompilationUnitTree tree, Trees trees )
	{
		m_tree = tree;
		m_trees = trees;
		m_positions = m_trees.getSourcePositions();
		m_classNameIndex = Maps.newHashMap();
		
		// index all the class names from package imports
		for( ImportTree importTree : m_tree.getImports() )
		{
			// ignore static imports for now
			if( importTree.isStatic() )
			{
				continue;
			}
			
			// get the full and simple class names
			String fullName = Descriptor.toJvmName( importTree.getQualifiedIdentifier().toString() );
			String simpleName = fullName;
			String[] parts = fullName.split( "/" );
			if( parts.length > 0 )
			{
				simpleName = parts[parts.length - 1];
			}
			
			m_classNameIndex.put( simpleName, fullName );
		}
		
		// index the self class using the package name
		String packageName = Descriptor.toJvmName( m_tree.getPackageName().toString() );
		for( Tree typeTree : m_tree.getTypeDecls() )
		{
			if( typeTree instanceof ClassTree )
			{
				ClassTree classTree = (ClassTree)typeTree;
				String className = classTree.getSimpleName().toString();
				m_classNameIndex.put( className, packageName + "/" + className );
			}
		}
	}

	public int getStart( Tree node )
	{
		return (int)m_positions.getStartPosition( m_tree, node );
	}

	public int getEnd( Tree node )
	{
		return (int)m_positions.getEndPosition( m_tree, node );
	}
	
	public int getLine( Tree node )
	{
		return getLine( getStart( node ) );
	}
	
	public int getLine( int pos )
	{
		return (int)m_tree.getLineMap().getLineNumber( pos );
	}
	
	public CharSequence getSource( )
	{
		try
		{
			return m_tree.getSourceFile().getCharContent( true );
		}
		catch( IOException ex )
		{
			throw new Error( ex );
		}
	}
	
	public CharSequence getSource( Tree node )
	{
		return getSource().subSequence( getStart( node ), getEnd( node ) );
	}

	public void visit( TreeVisitor visitor )
	{
		m_tree.accept( visitor, this );
	}
	
	public String getFullClassName( String simpleClassName )
	{
		String fullClassName = m_classNameIndex.get( simpleClassName );
		if( fullClassName == null )
		{
			// no mapping was found, the name is probably already fully-qualified
			fullClassName = simpleClassName;
		}
		return fullClassName;
	}
}