root/org.axdt.as3/src/org/axdt/as3/imp/parser/ResolvingVisitor.java @ 5c182b6e475d5851c54cdb2117f25af21723b62a

Revision 5c182b6e475d5851c54cdb2117f25af21723b62a, 8.1 KB (checked in by mb0 <mb0@…>, 15 months ago)

memory clean up ! (and several minor fixes)

  • merged symboltablevisitor and indexingvisitor together with some basic syntax checks to form as3analysis
  • index0r can now be used to request details on demand.
  • axdoc parser ignores whitespace textnodes and now parses the member code span
  • axdoc model: moved level property to indexnode and changed it to be persisted
  • changed axlevel literals
  • discover memory leak  http://bugs.eclipse.org/281790, cleaned up with editor service.
  • moved usefull generally useful methods out of as3 content proposer into as3 source helper
  • when no index exists for a source folder the project will be built and cached.
  • builder does not cache anymore instead builds two times. the first time to index. the second time to resolve.
  • lexer helper error detection fixed ater working through the sparce documentation on lpgs deterministic parser.
  • moved top level symbol table to the program ast node
  • some minor parser changed
  • Property mode set to 100644
Line 
1package org.axdt.as3.imp.parser;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5
6import lpg.runtime.IAst;
7import lpg.runtime.ILexStream;
8
9import org.axdt.as3.AS3Plugin;
10import org.axdt.as3.imp.parser.Ast.ASTNode;
11import org.axdt.as3.imp.parser.Ast.AssignmentExpression;
12import org.axdt.as3.imp.parser.Ast.Block;
13import org.axdt.as3.imp.parser.Ast.ClassDefinition;
14import org.axdt.as3.imp.parser.Ast.ExpressionStatement;
15import org.axdt.as3.imp.parser.Ast.ExtendsList;
16import org.axdt.as3.imp.parser.Ast.FunctionDefinition;
17import org.axdt.as3.imp.parser.Ast.IName;
18import org.axdt.as3.imp.parser.Ast.ITypeExpression_allowin;
19import org.axdt.as3.imp.parser.Ast.Ident;
20import org.axdt.as3.imp.parser.Ast.ImportDirective;
21import org.axdt.as3.imp.parser.Ast.Inheritance;
22import org.axdt.as3.imp.parser.Ast.InterfaceDefinition;
23import org.axdt.as3.imp.parser.Ast.Name;
24import org.axdt.as3.imp.parser.Ast.NewExpression;
25import org.axdt.as3.imp.parser.Ast.PackageDefinition;
26import org.axdt.as3.imp.parser.Ast.Parameters;
27import org.axdt.as3.imp.parser.Ast.RestParameter;
28import org.axdt.as3.imp.parser.Ast.ResultType;
29import org.axdt.as3.imp.parser.Ast.TypeExpressionList;
30import org.axdt.as3.imp.parser.Ast.TypedIdentifier;
31import org.axdt.as3.util.AS3ASTUtil;
32import org.axdt.as3.util.AS3Util;
33import org.axdt.axdoc.model.AXEntry;
34import org.axdt.axdoc.model.AXIndex;
35import org.axdt.axdoc.model.AXRoot;
36import org.axdt.axdoc.util.Index0r;
37import org.axdt.common.preferences.AxdtPreferences;
38import org.eclipse.core.resources.IFile;
39
40public class ResolvingVisitor extends DiagnoseVisitor {
41        private Index0r index0r;
42        private boolean addDebugErrors;
43        private ArrayList<AXIndex> importedPackages;
44        private ArrayList<AXEntry> importedTypes;
45        private String expectedPackageName;
46        public ResolvingVisitor(AS3ParseController pc) {
47                this(pc.getProject().getRawProject().getFile(pc.getPath()), pc.getLexer().getILexStream());
48        }
49        public ResolvingVisitor(IFile file, ILexStream stream) {
50                super(file, stream);
51                addDebugErrors = AS3Plugin.getDefault() != null && AxdtPreferences.doDebug();
52                index0r = Index0r.getInstance();
53                expectedPackageName = AS3Util.getExpectedPackageName(getFile());
54                resetImportCache();
55        }
56        protected void resetImportCache() {
57                importedPackages = new ArrayList<AXIndex>();
58                importedTypes = new ArrayList<AXEntry>();
59                for (AXRoot root:index0r.getRoots()) {
60                        // if has toplevel entries
61                        if (root.getEntries().size() > 0) {
62                                // add as default import
63                                importedPackages.add(root);
64                        }
65                }
66                // add same package
67                AXIndex[] sameIndexes = index0r.findPackage(expectedPackageName);
68                for (AXIndex index:sameIndexes) {
69                        importedPackages.add(index);
70                }
71                // file private names are resolved with the local symbol table
72        }
73        protected AXEntry resolveType(String name) {
74                for (AXEntry entry:importedTypes) {
75                        if (entry.getName().equals(name)) {
76                                index0r.requestFull(entry);
77                                return entry;
78                        }
79                }
80                for (AXIndex index:importedPackages) {
81                        for (AXEntry entry:index.getTypes()) {
82                                if (entry.getName().equals(name)) {
83                                        index0r.requestFull(entry);
84                                        return entry;
85                                }
86                        }
87                }
88                return null;
89        }
90        protected Object resolveType(Object type) {
91                return type instanceof ASTNode ? resolveNode((ASTNode) type) : null;
92        }
93        protected Object resolveConstructor(Object type) {
94                if (type == null) return null;
95                String typeName = type.toString();
96                AXEntry entry = resolveType(typeName);
97                Object declaration = null;
98                if (entry != null) {
99                        AXEntry member = entry.localMember(typeName);
100                        if (member != null){
101                                declaration = member.getId();
102                        } else {
103                                declaration = entry.getId();
104                        }
105                } else {
106                        // might be file private member
107                        SymbolTable table = AS3ASTUtil.getEnclosingSymbolTable((IAst)type).getRoot();
108                        declaration = table.findDeclaration(typeName);
109                }
110                setDeclaration(type, declaration);
111                return declaration;
112        }
113        protected Object resolveNode(ASTNode type) {
114                if (type == null) return null;
115                Object declaration = null;
116                String typeName = type.toString();
117                if (typeName.equals("*")) {
118                        declaration = "*";
119                } else {
120                        AXEntry entry = resolveType(typeName);
121                        if (entry != null) {
122                                declaration = entry.getId();
123                        } else {
124                                // might be file private member
125                                SymbolTable table = AS3ASTUtil.getEnclosingSymbolTable(type).getRoot();
126                                declaration = table.findDeclaration(typeName);
127                        }
128                }
129                setDeclaration(type, declaration);
130                return declaration;
131        }
132        protected void setDeclaration(Object type, Object declaration) {
133                if (declaration != null) {
134                        if (type instanceof Ident) {
135                                ((Ident)type).setDeclaration(declaration);
136                        } else if (addDebugErrors) {
137                                emitError((ASTNode)type, "todo: not expected other than ident");
138                        }
139                } else {
140                        emitError((ASTNode)type, "could not resolve type");
141                }
142        }
143        protected void resolveTypes(TypeExpressionList list) {
144                if (list != null) {
145                        for (int i=0; i < list.size();i++) {
146                                ITypeExpression_allowin superInterface = list.getTypeExpression_allowinAt(i);
147                                resolveNode((ASTNode)superInterface);
148                        }
149                }
150        }
151        @Override
152        public boolean visit(Block n) {
153                return true;
154        }
155
156        @Override
157        public boolean visit(PackageDefinition n) {
158                return true;
159        }
160        @Override
161        public void endVisit(PackageDefinition n) {
162                resetImportCache();
163        }
164        @Override
165        public boolean visit(ImportDirective n) {
166                Name name = (Name) n.getName();
167                boolean onDemand = n.getOnDemand()!=null;
168                boolean foundDeclaration = false;
169                if (name.getQualifier()==null||onDemand) {
170                        if (onDemand) {
171                                AXIndex[] findPackage = index0r.findPackage(name.toString());
172                                if (findPackage.length>=1) { 
173                                        foundDeclaration = true;
174                                        importedPackages.addAll(Arrays.asList(findPackage));
175                                        name.getIdent().setDeclaration(findPackage[0].getId());
176                                } else if (addDebugErrors) {
177                                        emitError(name, "could not resolve import");
178                                }
179                        } else {
180                                // does anyone want to import toplevel members ?
181                                emitError(name, "unused import. toplevel members can be used without import.");
182                        }
183                } else {
184                        AXEntry[] findMember = index0r.findMember(name.getQualifier().toString(), name.getIdent().toString());
185                        if (findMember.length>=1) {
186                                foundDeclaration = true;
187                                importedTypes.addAll(Arrays.asList(findMember));
188                                name.getIdent().setDeclaration(findMember[0].getId());
189                        } else if (addDebugErrors) {
190                                emitError(name, "could not resolve import");
191                        }
192                }
193                IName qualifier = name.getQualifier();
194                while (foundDeclaration && qualifier != null) {
195                        Name qname = (Name) qualifier;
196                        qname.getIdent().setDeclaration(Boolean.TRUE);
197                        qualifier = qname.getQualifier();
198                }
199                return false;
200        }
201        @Override
202        public boolean visit(Inheritance n) {
203                ClassDefinition parent = (ClassDefinition) n.getParent();
204                ITypeExpression_allowin superClass = n.getExtends();
205                resolveType(superClass);
206                resolveTypes(n.getImplements());
207                return false;
208        }
209        @Override
210        public boolean visit(ExtendsList n) {
211                InterfaceDefinition parent = (InterfaceDefinition) n.getParent();
212                resolveTypes(n.getExtends());
213                return false;
214        }
215       
216        @Override
217        public boolean visit(FunctionDefinition n) {
218                Ident name = n.getName();
219                if (name == null) {
220                        emitError(n, "must have a name");
221                        // TODO check for overrides ?
222                        //
223                }
224                return true;
225        }
226        @Override
227        public boolean visit(RestParameter n) {
228                // TODO: move to more basic checking phase
229                IAst parent = n.getParent();
230                if (parent instanceof Parameters) {
231                        Parameters params = (Parameters) parent;
232                        if (n != params.getParameterAt(params.size()-1)) {
233                                emitError(n, "rest parameter can only occur as last parameter");
234                        }
235                } else {
236                        emitError(parent, "todo: rest parameters parent should be parameters ?!");
237                }
238                return true;
239        }
240        @Override
241        public boolean visit(TypedIdentifier n) {
242                if (n != null) {
243                        resolveNode(n.getType());
244                        n.getName().setDeclaration(Boolean.FALSE);
245                }
246                return false;
247        }
248        @Override
249        public boolean visit(ResultType n) {
250                if (n != null)
251                        resolveType(n.getType());
252                return false;
253        }
254        @Override
255        public void endVisit(NewExpression n) {
256                // TODO check expression for type
257                if (n != null) {
258                        resolveConstructor(n.getExpression());
259                }
260        }
261        @Override
262        public void endVisit(AssignmentExpression n) {
263                // TODO check if left type is assignable from right type
264                n.toString();
265        }
266        @Override
267        public boolean visit(ExpressionStatement n) {
268                return true;
269        }
270}
Note: See TracBrowser for help on using the browser.