001: package tide.classsyntax;
002:
003: import tide.sources.FileItem;
004: import snow.texteditor.*;
005: import tide.utils.SyntaxUtils;
006: import snow.utils.StringUtils;
007: import javaparser.*;
008: import java.util.*;
009:
010: /** class ResolvedElement. part of an expresion chain like a.b.c
011: * can be a Constructor, a Method, a Class (static), a Field, a local variable
012: */
013: public final class ResolvedElement {
014: private ElementKind kind = ElementKind.Unknown;
015:
016: public final IDChain iDResolver;
017: private String name; // field or method name
018: private String typeName;
019: private String typeParams;
020: // positive incr for declarations (type), negative incr for names (invocations).
021: // a positive global value means that we have an array object !
022: private int arrayDepth = 0;
023: private String args;
024:
025: // javax.swing.JFrame instead of JFrame, if known
026: // inner classes have no fileItem, but an reflectedObject set
027: public FileItem resolvedType = null;
028:
029: // class, method or Constructor corresponding to this element, if reflected !!
030: public Object reflectedObject = null;
031:
032: // int, double, ...
033: public boolean isPrimitiveType = false;
034:
035: /** used to know if chains are valid or not
036: */
037: public boolean isResolved() {
038: if (isPrimitiveType)
039: return true; // ??
040: if (reflectedObject != null)
041: return true;
042: if (resolvedType != null)
043: return true;
044: return false;
045: }
046:
047: /** use for methods such as "super()" or "hello(12)"
048: */
049: public ResolvedElement(IDChain iDResolver, String methodName,
050: String args, boolean enforceMethod,
051: boolean enforceConstructor) {
052: this .iDResolver = iDResolver;
053: this .name = methodName;
054: this .args = args;
055:
056: if (enforceConstructor) {
057: kind = ElementKind.Constructor;
058: typeName = methodName;
059: } else if (enforceMethod || args != null) {
060: kind = ElementKind.Method;
061: } else {
062: kind = ElementKind.Field;
063: }
064:
065: readNameArrayDepth();
066: }
067:
068: public void setIsDirectClassCall() {
069: kind = ElementKind.Class;
070: }
071:
072: /** called when "this" or "super" calles
073: */
074: public void setIsConstructorCall(String typeName) {
075: kind = ElementKind.Constructor;
076: this .typeName = typeName;
077: this .name = typeName; // to test
078: }
079:
080: public void setIsPackagePart(FileItem fi) {
081: kind = ElementKind.PackageNameFragment;
082: resolvedType = fi;
083: typeName = fi.getJavaName();
084: }
085:
086: public String getName() {
087: return name;
088: }
089:
090: /** for example "String" or "java.lang.String"
091: */
092: private String getTypeMaybeUnresolved() {
093: return typeName;
094: }
095:
096: /** maybe unresolved
097: */
098: public void setTypeName(String t) {
099: typeName = t;
100: }
101:
102: public int getArrayDepth() {
103: return this .arrayDepth;
104: }
105:
106: /** either class name of reflectedObject (if class) or resolvedType type if non null or the simple type name
107: */
108: public String getTypeMaybeResolved() {
109: if (reflectedObject instanceof Class) {
110: return ((Class) reflectedObject).getName();
111: } else if (resolvedType != null) {
112: return resolvedType.getJavaName();
113: } else {
114: return getTypeMaybeUnresolved();
115: }
116: }
117:
118: private void readNameArrayDepth() {
119: if (name != null && name.indexOf('[') > 0) {
120: arrayDepth -= StringUtils.count(name, '['); // NEG !
121: name = name.substring(0, name.indexOf('['));
122: }
123: }
124:
125: public ElementKind getKind() {
126: return kind;
127: }
128:
129: /** for example String[] or LLjava.lang.String;;
130: */
131: public void setTypeWithParamsAndResolve(String tp) {
132: String[] tt = SyntaxUtils.splitTypeParams(tp);
133: if (tt != null) {
134: typeName = tt[0];
135: typeParams = tt[1];
136:
137: // detect array depths !
138: if (typeName != null) {
139: // todo: nested arrays int[][]
140: if (typeName.endsWith("[I")) {
141: arrayDepth += StringUtils.count(typeName, '[');
142: typeName = "int";
143: } else if (typeName.endsWith("[Z")) {
144: arrayDepth += StringUtils.count(typeName, '[');
145: typeName = "boolean";
146: } else if (typeName.endsWith("[B")) {
147: arrayDepth += StringUtils.count(typeName, '[');
148: typeName = "byte";
149: } else if (typeName.endsWith("[C")) {
150: arrayDepth += StringUtils.count(typeName, '[');
151: typeName = "char";
152: } else if (typeName.endsWith("[S")) {
153: arrayDepth += StringUtils.count(typeName, '[');
154: typeName = "short";
155: } else if (typeName.endsWith("[D")) {
156: arrayDepth += StringUtils.count(typeName, '[');
157: typeName = "double";
158: } else if (typeName.endsWith("[F")) {
159: arrayDepth += StringUtils.count(typeName, '[');
160: typeName = "float";
161: } else if (typeName.endsWith(";")) // [[[Lxxx; // reflection arrays
162: {
163: // count the [
164: while (typeName.startsWith("[")) {
165: typeName = typeName.substring(1);
166: arrayDepth += 1;
167: }
168: // remove the ";"
169: typeName = typeName.substring(0,
170: typeName.length() - 1);
171: } else if (typeName.indexOf('[') > 0) {
172: arrayDepth += StringUtils.count(typeName, '['); // POS
173: typeName = typeName.substring(0, typeName
174: .indexOf('['));
175: }
176: }
177: }
178:
179: isPrimitiveType = SyntaxUtils.isPrimitiveType(typeName);
180:
181: // resolve if not already
182: if (typeName != null && resolvedType == null) {
183: // always use the imports, also if not first, but
184: // TODO ??
185: resolvedType = iDResolver.locateTypeUsingImports(typeName);
186: }
187: }
188:
189: @Override
190: public String toString() {
191: StringBuffer sb = new StringBuffer("" + kind + " ");
192:
193: boolean resolved = (resolvedType != null || reflectedObject != null);
194:
195: String type = this .getTypeMaybeResolved();
196:
197: if (kind == ElementKind.Class) {
198: sb.append(type);
199: } else if (kind == ElementKind.Method) {
200: sb.append(name + " (args=" + args + ", ret=" + type
201: + ", type params=" + typeParams + ")");
202: } else if (kind == ElementKind.Field) {
203: sb.append(name + " (type=" + type + ", type params="
204: + typeParams + ")");
205: } else if (kind == ElementKind.Constructor) {
206: sb.append(name + " (args=" + args + ", ret=" + type
207: + ", type params=" + typeParams + ")");
208: } else if (kind == ElementKind.PackageNameFragment) {
209: sb.append(name);
210: } else {
211: sb.append("??????");
212: }
213:
214: if (arrayDepth != 0) {
215: sb.append(" (arraydepth=" + arrayDepth + ")");
216: }
217:
218: if (!resolved) {
219: sb.append(" (NOT resolved)");
220: }
221:
222: return sb.toString();
223: }
224:
225: }
|