Add JVM compiler support.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
24 * If you wish your version of this file to be governed by only the CDDL
25 * or only the GPL Version 2, indicate your decision by adding
26 * "[Contributor] elects to include this software in this distribution
27 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28 * single choice of license, a recipient has the option to distribute
29 * your version of this file under either the CDDL, the GPL Version 2 or
30 * to extend the choice of license to its licensees as provided above.
31 * However, if you add GPL Version 2 code and therefore, elected the GPL
32 * Version 2 license, then the option applies only if the new code is
33 * made subject to such option by the copyright holder.
37 * Portions Copyrighted 2008 Sun Microsystems, Inc.
39 package org.netbeans.modules.ada.editor.parser;
41 import org.netbeans.modules.ada.editor.ast.nodes.Program;
42 import org.netbeans.modules.ada.editor.ast.nodes.Identifier;
43 import org.netbeans.modules.ada.editor.ast.ASTNode;
44 import java.util.ArrayList;
45 import java.util.Collections;
46 import java.util.HashMap;
47 import java.util.List;
50 import java.util.logging.Logger;
51 import javax.swing.ImageIcon;
52 import javax.swing.text.Document;
53 import org.netbeans.modules.ada.editor.CodeUtils;
54 import org.netbeans.modules.ada.editor.ast.ASTError;
55 import org.netbeans.modules.ada.editor.ast.ASTUtils;
56 import org.netbeans.modules.ada.editor.ast.nodes.Block;
57 import org.netbeans.modules.ada.editor.ast.nodes.BlockStatement;
58 import org.netbeans.modules.ada.editor.ast.nodes.Comment;
59 import org.netbeans.modules.ada.editor.ast.nodes.Expression;
60 import org.netbeans.modules.ada.editor.ast.nodes.FieldsDeclaration;
61 import org.netbeans.modules.ada.editor.ast.nodes.FormalParameter;
62 import org.netbeans.modules.ada.editor.ast.nodes.MethodDeclaration;
63 import org.netbeans.modules.ada.editor.ast.nodes.PackageBody;
64 import org.netbeans.modules.ada.editor.ast.nodes.PackageSpecification;
65 import org.netbeans.modules.ada.editor.ast.nodes.SubprogramBody;
66 import org.netbeans.modules.ada.editor.ast.nodes.SubprogramSpecification;
67 import org.netbeans.modules.ada.editor.ast.nodes.TypeAccess;
68 import org.netbeans.modules.ada.editor.ast.nodes.TypeDeclaration;
69 import org.netbeans.modules.ada.editor.ast.nodes.TypeName;
70 import org.netbeans.modules.ada.editor.ast.nodes.Variable;
71 import org.netbeans.modules.ada.editor.ast.nodes.visitors.DefaultVisitor;
72 import org.netbeans.modules.ada.editor.parser.AdaElementHandle.SubprogramSpecificationHandle;
73 import org.netbeans.modules.ada.editor.parser.AdaElementHandle.MethodSubprogSpecHandle;
74 import org.netbeans.modules.ada.editor.parser.AdaElementHandle.MethodSubprogBodyHandle;
75 import org.netbeans.modules.ada.editor.parser.AdaElementHandle.PackageBodyHandle;
76 import org.netbeans.modules.ada.editor.parser.AdaElementHandle.PackageSpecificationHandle;
77 import org.netbeans.modules.ada.editor.parser.AdaElementHandle.SubprogramBodyHandle;
78 import org.netbeans.modules.csl.api.ElementHandle;
79 import org.netbeans.modules.csl.api.ElementKind;
80 import org.netbeans.modules.csl.api.HtmlFormatter;
81 import org.netbeans.modules.csl.api.Modifier;
82 import org.netbeans.modules.csl.api.OffsetRange;
83 import org.netbeans.modules.csl.api.StructureItem;
84 import org.netbeans.modules.csl.api.StructureScanner;
85 import org.netbeans.modules.csl.spi.ParserResult;
86 import org.netbeans.modules.parsing.api.Source;
87 import org.openide.util.ImageUtilities;
90 * Based on org.netbeans.modules.php.editor.parser.PhpStructureScanner
92 * @author Andrea Lucarelli
94 public class AdaStructureScanner implements StructureScanner {
96 private static final Logger LOGGER = Logger.getLogger(AdaStructureScanner.class.getName());
97 private static ImageIcon TYPE_ICON = null;
98 private static ImageIcon TYPE_PRIVATE_ICON = null;
99 private ParserResult info;
100 private static final String FOLD_CODE_BLOCKS = "codeblocks"; //NOI18N
101 private static final String FOLD_PACKAGE = "codeblocks"; //NOI18N
102 private static final String FOLD_ADADOC = "comments"; //NOI18N
103 private static final String FOLD_COMMENT = "initial-comment"; //NOI18N
104 private static final String FONT_GRAY_COLOR = "<font color=\"#999999\">"; //NOI18N
105 private static final String CLOSE_FONT = "</font>"; //NOI18N
106 private static final String LAST_CORRECT_FOLDING_PROPERTY = "LAST_CORRECT_FOLDING_PROPERY";
108 public List<? extends StructureItem> scan(final ParserResult info) {
110 Program program = ASTUtils.getRoot(info);
111 final List<StructureItem> items = new ArrayList<StructureItem>();
112 if (program != null) {
113 program.accept(new StructureVisitor(items, program));
116 return Collections.emptyList();
119 public Map<String, List<OffsetRange>> folds(ParserResult info) {
120 Program program = ASTUtils.getRoot(info);
121 final Map<String, List<OffsetRange>> folds = new HashMap<String, List<OffsetRange>>();
122 if (program != null) {
123 if (program.getStatements().size() == 1) {
124 // check whether the ast is broken.
125 if (program.getStatements().get(0) instanceof ASTError) {
126 @SuppressWarnings("unchecked")
127 Map<String, List<OffsetRange>> lastCorrect = (Map<String, List<OffsetRange>>) info.getSnapshot().getSource().getDocument(false).getProperty(LAST_CORRECT_FOLDING_PROPERTY);
128 if (lastCorrect != null) {
131 return Collections.emptyMap();
135 (new FoldVisitor(folds)).scan(program);
136 List<Comment> comments = program.getComments();
137 if (comments != null) {
138 for (Comment comment : comments) {
139 // TODO: for ada doc and spark ???
142 Source source = info.getSnapshot().getSource();
143 assert source != null : "source was null";
144 Document doc = source.getDocument(false);
146 doc.putProperty(LAST_CORRECT_FOLDING_PROPERTY, folds);
150 return Collections.emptyMap();
153 private OffsetRange createOffsetRange(ASTNode node) {
154 return new OffsetRange(node.getStartOffset(), node.getEndOffset());
157 private List<OffsetRange> getRanges(Map<String, List<OffsetRange>> folds, String kind) {
158 List<OffsetRange> ranges = folds.get(kind);
159 if (ranges == null) {
160 ranges = new ArrayList<OffsetRange>();
161 folds.put(kind, ranges);
166 public Configuration getConfiguration() {
170 private class StructureVisitor extends DefaultVisitor {
172 final List<StructureItem> items;
173 private List<StructureItem> children = null;
174 private Program program;
175 private PackageSpecification pkgspc;
176 private PackageBody pkgbdy;
178 public StructureVisitor(List<StructureItem> items, Program program) {
179 //LOGGER.setLevel(Level.FINE);
181 this.program = program;
184 public StructureVisitor(List<StructureItem> items, PackageSpecification pkgspc) {
185 //LOGGER.setLevel(Level.FINE);
187 this.pkgspc = pkgspc;
190 public StructureVisitor(List<StructureItem> items, PackageBody pkgbdy) {
191 //LOGGER.setLevel(Level.FINE);
193 this.pkgbdy = pkgbdy;
197 public void visit(SubprogramSpecification subprogSpec) {
198 if (children == null && subprogSpec.getSubprogramName() != null) {
199 AdaStructureItem item = new AdaSubprogSpecStructureItem(new AdaElementHandle.SubprogramSpecificationHandle(info, subprogSpec));
205 public void visit(SubprogramBody procedure) {
206 if (children == null && procedure.getSubprogramSpecification().getSubprogramName() != null) {
207 AdaStructureItem item = new AdaSubprogBodyStructureItem(new AdaElementHandle.SubprogramBodyHandle(info, procedure));
213 public void visit(PackageSpecification pkgspc) {
214 if (pkgspc.getName() != null) {
215 LOGGER.fine(pkgspc.getName().getName());
216 if (children == null) {
217 children = new ArrayList<StructureItem>();
219 AdaStructureItem item = new AdaPackageSpecificationStructureItem(new AdaElementHandle.PackageSpecificationHandle(info, pkgspc), children); //NOI18N
222 final List<StructureItem> subitems = new ArrayList<StructureItem>();
223 pkgspc.accept(new StructureVisitor(subitems, pkgspc));
224 children.addAll(subitems);
230 public void visit(PackageBody pkgbdy) {
231 if (pkgbdy.getName() != null) {
232 LOGGER.fine(pkgbdy.getName().getName());
233 if (children == null) {
234 children = new ArrayList<StructureItem>();
236 AdaStructureItem item = new AdaPackageBodyStructureItem(new AdaElementHandle.PackageBodyHandle(info, pkgbdy), children); //NOI18N
239 final List<StructureItem> subitems = new ArrayList<StructureItem>();
240 pkgbdy.accept(new StructureVisitor(subitems, pkgbdy));
241 children.addAll(subitems);
247 public void visit(FieldsDeclaration fields) {
248 Variable[] variables = fields.getVariableNames();
249 if (variables != null) {
250 for (Variable variable : variables) {
251 String name = ASTUtils.resolveVariableName(variable);
255 AdaStructureItem item = new AdaSimpleStructureItem(new AdaElementHandle.FieldsDeclarationHandle(info, fields), text, "0"); //NOI18N
263 public void visit(TypeDeclaration type) {
264 Identifier id = type.getTypeName();
266 String name = id.getName();
270 AdaStructureItem item = new AdaTypeStructureItem(new AdaElementHandle.TypeDeclarationHandle(info, type), text, "0"); //NOI18N
277 public void visit(MethodDeclaration method) {
278 if (children == null) {
281 LOGGER.fine(method.getMethodName());
282 if (method.getSubprogramBody() != null) {
283 SubprogramBody subprog = method.getSubprogramBody();
284 if (subprog != null && subprog.getSubprogramSpecification().getSubprogramName() != null) {
285 AdaStructureItem item;
286 // className doesn't have to be defined if it's interace
287 item = new AdaMethodSubprogBodyStructureItem(new AdaElementHandle.MethodSubprogBodyHandle(info, method));
291 SubprogramSpecification subprog = method.getSubprogramSpecification();
292 if (subprog != null && subprog.getSubprogramName() != null) {
293 AdaStructureItem item;
294 // className doesn't have to be defined if it's interace
295 item = new AdaMethodSubprogSpecStructureItem(new AdaElementHandle.MethodSubprogSpecHandle(info, method));
302 private abstract class AdaStructureItem implements StructureItem {
304 final private AdaElementHandle elementHandle;
305 final private List<? extends StructureItem> children;
306 final private String sortPrefix;
308 public AdaStructureItem(AdaElementHandle elementHandle, List<? extends StructureItem> children, String sortPrefix) {
309 this.elementHandle = elementHandle;
310 this.sortPrefix = sortPrefix;
311 if (children != null) {
312 this.children = children;
314 this.children = Collections.emptyList();
319 public boolean equals(Object obj) {
320 boolean thesame = false;
321 if (obj instanceof AdaStructureItem) {
322 AdaStructureItem item = (AdaStructureItem) obj;
323 if (item.getName() != null && this.getName() != null) {
324 thesame = item.elementHandle.getName().equals(elementHandle.getName()) && item.elementHandle.getASTNode().getStartOffset() == elementHandle.getASTNode().getStartOffset();
331 public int hashCode() {
332 //int hashCode = super.hashCode();
334 if (getName() != null) {
335 hashCode = 31 * getName().hashCode() + hashCode;
337 hashCode = (int) (31 * getPosition() + hashCode);
341 public String getName() {
342 return elementHandle.getName();
345 public String getSortText() {
346 return sortPrefix + elementHandle.getName();
349 public ElementHandle getElementHandle() {
350 return elementHandle;
353 public ElementKind getKind() {
354 return elementHandle.getKind();
357 public Set<Modifier> getModifiers() {
358 return elementHandle.getModifiers();
361 public boolean isLeaf() {
362 return (children.size() == 0);
365 public List<? extends StructureItem> getNestedItems() {
369 public long getPosition() {
370 return elementHandle.getASTNode().getStartOffset();
373 public long getEndPosition() {
374 return elementHandle.getASTNode().getEndOffset();
377 public ImageIcon getCustomIcon() {
381 protected void appendSubprogDescription(SubprogramSpecification subprog, HtmlFormatter formatter) {
383 if (subprog == null || subprog.getSubprogramName() == null) {
386 formatter.appendText(subprog.getSubprogramName().getName());
387 formatter.appendText("("); //NOI18N
389 List<FormalParameter> parameters = subprog.getFormalParameters();
390 if (parameters != null && parameters.size() > 0) {
391 boolean first = true;
392 for (FormalParameter formalParameter : parameters) {
394 Expression parameter = formalParameter.getParameterName();
395 if (parameter != null) {
396 Variable variable = null;
397 if (parameter instanceof Variable) {
398 variable = (Variable) parameter;
401 if (variable != null) {
402 name = ASTUtils.resolveVariableName(variable);
404 name = "??"; //NOI18N
408 if (formalParameter.getParameterType() != null) {
409 type = CodeUtils.extractTypeName(formalParameter.getParameterType());
413 formatter.appendText("; "); //NOI18N
416 formatter.appendText(name);
419 formatter.appendText(" : "); //NOI18N
420 FormalParameter.Mode mode = formalParameter.getParameterMode();
421 formatter.appendHtml(FONT_GRAY_COLOR);
422 if (mode == FormalParameter.Mode.IN) {
423 formatter.appendText("in "); //NOI18N
424 } else if (mode == FormalParameter.Mode.OUT) {
425 formatter.appendText("out "); //NOI18N
426 } else if (mode == FormalParameter.Mode.IN_OUT) {
427 formatter.appendText("in out "); //NOI18N
429 formatter.appendText(type);
430 formatter.appendHtml(CLOSE_FONT);
436 formatter.appendText(")"); //NOI18N
438 if (subprog.getSubtypeReturn() != null) {
439 String type = subprog.getSubtypeReturn().getName();
440 formatter.appendText(" : out "); //NOI18N
441 formatter.appendHtml(FONT_GRAY_COLOR);
442 formatter.appendText(type);
443 formatter.appendHtml(CLOSE_FONT);
448 protected void appendSubprogDescription(SubprogramBody subprog, HtmlFormatter formatter) {
450 if (subprog == null || subprog.getSubprogramSpecification().getSubprogramName() == null) {
453 formatter.appendText(subprog.getSubprogramSpecification().getSubprogramName().getName());
454 formatter.appendText("("); //NOI18N
456 List<FormalParameter> parameters = subprog.getSubprogramSpecification().getFormalParameters();
457 if (parameters != null && parameters.size() > 0) {
458 boolean first = true;
459 for (FormalParameter formalParameter : parameters) {
461 Expression parameter = formalParameter.getParameterName();
462 if (parameter != null) {
463 Variable variable = null;
464 if (parameter instanceof Variable) {
465 variable = (Variable) parameter;
468 if (variable != null) {
469 name = ASTUtils.resolveVariableName(variable);
471 name = "??"; //NOI18N
475 if (formalParameter.getParameterType() != null) {
476 type = CodeUtils.extractTypeName(formalParameter.getParameterType());
480 formatter.appendText("; "); //NOI18N
483 formatter.appendText(name);
486 formatter.appendText(" : "); //NOI18N
487 FormalParameter.Mode mode = formalParameter.getParameterMode();
488 formatter.appendHtml(FONT_GRAY_COLOR);
489 if (mode == FormalParameter.Mode.IN) {
490 formatter.appendText("in "); //NOI18N
491 } else if (mode == FormalParameter.Mode.OUT) {
492 formatter.appendText("out "); //NOI18N
493 } else if (mode == FormalParameter.Mode.IN_OUT) {
494 formatter.appendText("in out "); //NOI18N
496 formatter.appendText(type);
497 formatter.appendHtml(CLOSE_FONT);
503 formatter.appendText(")"); //NOI18N
505 if (subprog.getSubprogramSpecification().getSubtypeReturn() != null) {
506 String type = subprog.getSubprogramSpecification().getSubtypeReturn().getName();
507 formatter.appendText(" : out "); //NOI18N
508 formatter.appendHtml(FONT_GRAY_COLOR);
509 formatter.appendText(type);
510 formatter.appendHtml(CLOSE_FONT);
515 private class AdaTypeStructureItem extends AdaStructureItem {
517 private static final String ADA_TYPE_ICON = "org/netbeans/modules/ada/editor/resources/icons/type_16.png"; //NOI18N
518 private static final String ADA_TYPE_PRIVATE_ICON = "org/netbeans/modules/ada/editor/resources/icons/type_private_16.png"; //NOI18N
519 private String simpleText;
521 public AdaTypeStructureItem(AdaElementHandle elementHandle, String simpleText, String prefix) {
522 super(elementHandle, null, prefix);
523 this.simpleText = simpleText;
527 public ImageIcon getCustomIcon() {
528 Set<Modifier> modifiers = this.getModifiers();
530 if (TYPE_ICON == null) {
531 TYPE_ICON = new ImageIcon(ImageUtilities.loadImage(ADA_TYPE_ICON));
534 ImageIcon icon = TYPE_ICON;
536 for (Modifier modifier : modifiers) {
537 if (modifier == Modifier.PRIVATE) {
538 if (TYPE_PRIVATE_ICON == null) {
539 TYPE_PRIVATE_ICON = new ImageIcon(ImageUtilities.loadImage(ADA_TYPE_PRIVATE_ICON));
541 icon = TYPE_PRIVATE_ICON;
547 public String getHtml(HtmlFormatter formatter) {
548 formatter.appendText(simpleText);
549 return formatter.getText();
553 private class AdaSimpleStructureItem extends AdaStructureItem {
555 private String simpleText;
557 public AdaSimpleStructureItem(AdaElementHandle elementHandle, String simpleText, String prefix) {
558 super(elementHandle, null, prefix);
559 this.simpleText = simpleText;
562 public String getHtml(HtmlFormatter formatter) {
563 formatter.appendText(simpleText);
564 return formatter.getText();
568 private class AdaSubprogSpecStructureItem extends AdaStructureItem {
570 public AdaSubprogSpecStructureItem(AdaElementHandle elementHandle) {
571 super(elementHandle, null, "subspc"); //NOI18N
574 public String getHtml(HtmlFormatter formatter) {
576 SubprogramSpecificationHandle handle = (SubprogramSpecificationHandle) getElementHandle();
577 SubprogramSpecification subprog = (SubprogramSpecification) handle.getASTNode();
578 appendSubprogDescription(subprog, formatter);
579 return formatter.getText();
583 private class AdaSubprogBodyStructureItem extends AdaStructureItem {
585 public AdaSubprogBodyStructureItem(AdaElementHandle elementHandle) {
586 super(elementHandle, null, "subbdy"); //NOI18N
589 public String getHtml(HtmlFormatter formatter) {
591 SubprogramBodyHandle handle = (SubprogramBodyHandle) getElementHandle();
592 SubprogramBody subprog = (SubprogramBody) handle.getASTNode();
593 appendSubprogDescription(subprog, formatter);
594 return formatter.getText();
598 private class AdaPackageSpecificationStructureItem extends AdaStructureItem {
600 public AdaPackageSpecificationStructureItem(AdaElementHandle elementHandle, List<? extends StructureItem> children) {
601 super(elementHandle, children, "pkgspc"); //NOI18N
604 public String getHtml(HtmlFormatter formatter) {
606 PackageSpecificationHandle handle = (PackageSpecificationHandle) getElementHandle();
607 formatter.appendText(handle.getName());
608 formatter.appendHtml(FONT_GRAY_COLOR + " (specification)" + CLOSE_FONT);
609 return formatter.getText();
613 private class AdaPackageBodyStructureItem extends AdaStructureItem {
615 public AdaPackageBodyStructureItem(AdaElementHandle elementHandle, List<? extends StructureItem> children) {
616 super(elementHandle, children, "pkgbdy"); //NOI18N
619 public String getHtml(HtmlFormatter formatter) {
621 PackageBodyHandle handle = (PackageBodyHandle) getElementHandle();
622 formatter.appendText(handle.getName());
623 formatter.appendHtml(FONT_GRAY_COLOR + " (body)" + CLOSE_FONT);
624 return formatter.getText();
628 private class AdaMethodSubprogSpecStructureItem extends AdaStructureItem {
630 public AdaMethodSubprogSpecStructureItem(AdaElementHandle elementHandle) {
631 super(elementHandle, null, "subspc"); //NOI18N
634 public String getHtml(HtmlFormatter formatter) {
636 MethodSubprogSpecHandle handle = (MethodSubprogSpecHandle) getElementHandle();
637 MethodDeclaration method = (MethodDeclaration) handle.getASTNode();
638 appendSubprogDescription(method.getSubprogramSpecification(), formatter);
639 return formatter.getText();
643 private class AdaMethodSubprogBodyStructureItem extends AdaStructureItem {
645 public AdaMethodSubprogBodyStructureItem(AdaElementHandle elementHandle) {
646 super(elementHandle, null, "subbdy"); //NOI18N
649 public String getHtml(HtmlFormatter formatter) {
651 MethodSubprogBodyHandle handle = (MethodSubprogBodyHandle) getElementHandle();
652 MethodDeclaration method = (MethodDeclaration) handle.getASTNode();
653 appendSubprogDescription(method.getSubprogramBody(), formatter);
654 return formatter.getText();
658 private class FoldVisitor extends DefaultVisitor {
660 final Map<String, List<OffsetRange>> folds;
661 private String foldType;
663 public FoldVisitor(Map<String, List<OffsetRange>> folds) {
665 this.foldType = null;
670 public void visit(PackageSpecification pkgspc) {
671 this.foldType = FOLD_PACKAGE;
672 if (pkgspc.getBody() != null) {
673 scan(pkgspc.getBody());
678 public void visit(PackageBody pkgbdy) {
679 this.foldType = FOLD_PACKAGE;
680 if (pkgbdy.getBody() != null) {
681 scan(pkgbdy.getBody());
686 public void visit(Block block) {
687 if (foldType != null) {
688 getRanges(folds, foldType).add(createOffsetRange(block));
691 if (block.getStatements() != null) {
692 scan(block.getStatements());
697 public void visit(BlockStatement block) {
698 if (foldType != null) {
699 getRanges(folds, foldType).add(createOffsetRange(block));
702 if (block.getDeclarations() != null) {
703 scan(block.getDeclarations());
705 if (block.getBody() != null) {
706 scan(block.getBody());
711 public void visit(SubprogramBody subprog) {
712 foldType = FOLD_CODE_BLOCKS;
713 if (subprog.getDeclarations() != null) {
714 scan(subprog.getDeclarations());
716 foldType = FOLD_CODE_BLOCKS;
717 if (subprog.getBody() != null) {
718 scan(subprog.getBody());