From 28ea258e7ed4e1e3fccd15cb66549b882bb27614 Mon Sep 17 00:00:00 2001
From: Jenkins June 22, 2007 The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at http://www.eclipse.org/legal/epl-v10.html.
+For purposes of the EPL, "Program" will mean the Content. If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at http://www.eclipse.org. Eclipse Public License - v 1.0
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE,
+REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
+OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a)
+in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and i)
+changes to the Program, and ii)
+additions to the Program; where
+such changes and/or additions to the Program originate from and are distributed
+by that particular Contributor. A Contribution 'originates' from a Contributor
+if it was added to the Program by such Contributor itself or anyone acting on
+such Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in conjunction
+with the Program under their own license agreement, and (ii) are not derivative
+works of the Program. "Contributor" means any person or
+entity that distributes the Program. "Licensed Patents " mean patent
+claims licensable by a Contributor which are necessarily infringed by the use
+or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions
+distributed in accordance with this Agreement. "Recipient" means anyone who
+receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a)
+Subject to the terms of this Agreement, each Contributor hereby grants Recipient
+a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly
+display, publicly perform, distribute and sublicense the Contribution of such
+Contributor, if any, and such derivative works, in source code and object code
+form. b)
+Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free
+patent license under Licensed Patents to make, use, sell, offer to sell, import
+and otherwise transfer the Contribution of such Contributor, if any, in source
+code and object code form. This patent license shall apply to the combination
+of the Contribution and the Program if, at the time the Contribution is added
+by the Contributor, such addition of the Contribution causes such combination
+to be covered by the Licensed Patents. The patent license shall not apply to
+any other combinations which include the Contribution. No hardware per se is
+licensed hereunder. c)
+Recipient understands that although each Contributor grants the licenses to its
+Contributions set forth herein, no assurances are provided by any Contributor
+that the Program does not infringe the patent or other intellectual property
+rights of any other entity. Each Contributor disclaims any liability to Recipient
+for claims brought by any other entity based on infringement of intellectual
+property rights or otherwise. As a condition to exercising the rights and
+licenses granted hereunder, each Recipient hereby assumes sole responsibility
+to secure any other intellectual property rights needed, if any. For example,
+if a third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license before
+distributing the Program. d)
+Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the
+Program in object code form under its own license agreement, provided that:
+ a)
+it complies with the terms and conditions of this Agreement; and b)
+its license agreement: i)
+effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; ii)
+effectively excludes on behalf of all Contributors all liability for damages,
+including direct, indirect, special, incidental and consequential damages, such
+as lost profits; iii)
+states that any provisions which differ from this Agreement are offered by that
+Contributor alone and not by any other party; and iv)
+states that source code for the Program is available from such Contributor, and
+informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange. When the Program is made available in source
+code form: a)
+it must be made available under this Agreement; and b) a
+copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any
+copyright notices contained within the Program. Each Contributor must identify itself as the
+originator of its Contribution, if any, in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may
+accept certain responsibilities with respect to end users, business partners
+and the like. While this license is intended to facilitate the commercial use
+of the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes the
+Program in a commercial product offering, such Contributor ("Commercial
+Contributor") hereby agrees to defend and indemnify every other
+Contributor ("Indemnified Contributor") against any losses, damages and
+costs (collectively "Losses") arising from claims, lawsuits and other
+legal actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may participate
+in any such claim at its own expense. For example, a Contributor might include the
+Program in a commercial product offering, Product X. That Contributor is then a
+Commercial Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance claims and
+warranties are such Commercial Contributor's responsibility alone. Under this
+section, the Commercial Contributor would have to defend claims against the
+other Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
+WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and distributing the
+Program and assumes all risks associated with its exercise of rights under this
+Agreement , including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
+THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid
+or unenforceable under applicable law, it shall not affect the validity or
+enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. All Recipient's rights under this Agreement
+shall terminate if it fails to comply with any of the material terms or
+conditions of this Agreement and does not cure such failure in a reasonable
+period of time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement Steward has
+the right to modify this Agreement. The Eclipse Foundation is the initial
+Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the
+State of New York and the intellectual property laws of the United States of
+America. No party to this Agreement will bring a legal action under this
+Agreement more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation. February 1, 2011 THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT. Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ ("EPL"). A copy of the EPL is provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.
+ For purposes of the EPL, "Program" will mean the Content. Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+ repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads"). The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and
+Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations: Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory. THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO): IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content. The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+ Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or
+ other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to
+ install, extend and update Eclipse-based products. Information about packaging Installable Software is available at http://eclipse.org/equinox/p2/repository_packaging.html
+ ("Specification"). You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+ applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+ in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+ Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following: Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted. Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both. like a browser.
+ // Instead of inserting an empty line, it just adds a single line break.
+ // Furthermore, the indentation of June 2, 2006 The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at http://www.eclipse.org/legal/epl-v10.html.
+For purposes of the EPL, "Program" will mean the Content. If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at http://www.eclipse.org.
+ * This class is not intended to be subclassed by clients.
+ *
+ * For example:
+ * About This Content
+
+License
+
+null
, if no source could be computed
+ * @throws CoreException if the source file could not be loaded or if there was a
+ * problem with the index
+ */
+ private String computeSourceForBinding(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] names = findDefsOrDecls(ast, binding);
+
+ // in case the binding is a non-explicit specialization we need
+ // to consider the original binding (bug 281396)
+ if (names.length == 0 && binding instanceof ICPPSpecialization) {
+ binding= ((ICPPSpecialization) binding).getSpecializedBinding();
+ if (!(binding instanceof IProblemBinding)) {
+ names= findDefsOrDecls(ast, binding);
+ }
+ }
+ if (names.length > 0) {
+ for (IName name : names) {
+ String source= computeSourceForName(name, binding);
+ if (source != null) {
+ return source;
+ }
+ }
+ }
+ return null;
+ }
+ /**
+ * Search for definitions or declarations for the given binding.
+ * @param ast the AST of the translation unit
+ * @param binding the binding
+ * @return an array of definitions or declarations, never null
+ * @throws CoreException
+ */
+ private IName[] findDefsOrDecls(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] names= findDefinitions(ast, binding);
+ if (names.length == 0) {
+ names= findDeclarations(ast, binding);
+ }
+ return names;
+ }
+ /**
+ * Search for definitions for the given binding.
+ *
+ * @param ast the AST of the translation unit
+ * @param binding the binding
+ * @return an array of definitions, never null
+ * @throws CoreException
+ */
+ private IName[] findDefinitions(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] declNames= ast.getDefinitionsInAST(binding);
+ if (declNames.length == 0 && ast.getIndex() != null) {
+ // search definitions in index
+ declNames = ast.getIndex().findNames(binding, IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
+ }
+ return declNames;
+ }
+ /**
+ * Search for declarations for the given binding.
+ *
+ * @param ast the AST of the translation unit
+ * @param binding the binding
+ * @return an array of declarations, never null
+ * @throws CoreException
+ */
+ private IName[] findDeclarations(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] declNames= ast.getDeclarationsInAST(binding);
+ if (declNames.length == 0 && ast.getIndex() != null) {
+ // search declarations in index
+ declNames= ast.getIndex().findNames(binding, IIndex.FIND_DECLARATIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
+ }
+ return declNames;
+ }
+ /**
+ * Get the source for the given name from the underlying file.
+ *
+ * @param name the name to get the source for
+ * @param binding the binding of the name
+ * @return the source string or null
, if the source could not be computed
+ * @throws CoreException if the file could not be loaded
+ */
+ private String computeSourceForName(IName name, IBinding binding) throws CoreException {
+ IASTFileLocation fileLocation= name.getFileLocation();
+ if (fileLocation == null) {
+ return null;
+ }
+ int nodeOffset= fileLocation.getNodeOffset();
+ int nodeLength= fileLocation.getNodeLength();
+
+ String fileName= fileLocation.getFileName();
+ //if (DEBUG) System.out.println("[CSourceHover] Computing source for " + name + " in " + fileName); //$NON-NLS-1$//$NON-NLS-2$
+ IPath location= Path.fromOSString(fileName);
+ LocationKind locationKind= LocationKind.LOCATION;
+ if (name instanceof IASTName && !name.isReference()) {
+ IASTName astName= (IASTName)name;
+ if (astName.getTranslationUnit().getFilePath().equals(fileName) && fTU.getResource() != null) {
+ // reuse editor buffer for names local to the translation unit
+ location= fTU.getResource().getFullPath();
+ locationKind= LocationKind.IFILE;
+ }
+ } else {
+ // try to resolve path to a resource for proper encoding (bug 221029)
+ IFile file= EditorUtility.getWorkspaceFileAtLocation(location, fTU);
+ if (file != null) {
+ location= file.getFullPath();
+ locationKind= LocationKind.IFILE;
+ if (name instanceof IIndexName) {
+ // need to adjust index offsets to current offsets
+ // in case file has been modified since last index time
+ IIndexName indexName= (IIndexName) name;
+ long timestamp= indexName.getFile().getTimestamp();
+ IPositionConverter converter= CCorePlugin.getPositionTrackerManager().findPositionConverter(file, timestamp);
+ if (converter != null) {
+ IRegion currentLocation= converter.historicToActual(new Region(nodeOffset, nodeLength));
+ nodeOffset= currentLocation.getOffset();
+ nodeLength= currentLocation.getLength();
+ }
+ }
+ }
+ }
+ ITextFileBufferManager mgr= FileBuffers.getTextFileBufferManager();
+ mgr.connect(location, locationKind, fMonitor);
+ ITextFileBuffer buffer= mgr.getTextFileBuffer(location, locationKind);
+ try {
+ IRegion nameRegion= new Region(nodeOffset, nodeLength);
+ final int nameOffset= nameRegion.getOffset();
+ final int sourceStart;
+ final int sourceEnd;
+ IDocument doc= buffer.getDocument();
+ if (nameOffset >= doc.getLength() || nodeLength <= 0) {
+ return null;
+ }
+ if (binding instanceof IMacroBinding) {
+ ITypedRegion partition= TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, nameOffset, false);
+ if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
+ int directiveStart= partition.getOffset();
+ int commentStart= searchCommentBackward(doc, directiveStart, -1);
+ if (commentStart >= 0) {
+ sourceStart= commentStart;
+ } else {
+ sourceStart= directiveStart;
+ }
+ sourceEnd= directiveStart + partition.getLength();
+ } else {
+ return null;
+ }
+ } else {
+ // expand source range to include preceding comment, if any
+ boolean isKnR= isKnRSource(name);
+ sourceStart= computeSourceStart(doc, nameOffset, binding, isKnR);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return null;
+ }
+ sourceEnd= computeSourceEnd(doc, nameOffset + nameRegion.getLength(), binding, name.isDefinition(), isKnR);
+ }
+ String source= buffer.getDocument().get(sourceStart, sourceEnd - sourceStart);
+ return source;
+
+ } catch (BadLocationException exc) {
+ // ignore - should not happen anyway
+ //if (DEBUG) exc.printStackTrace();
+ } finally {
+ mgr.disconnect(location, LocationKind.LOCATION, fMonitor);
+ }
+ return null;
+ }
+ /**
+ * Searches the start of the comment preceding the given source offset.
+ * Continuous line comments are considered as one comment until a block
+ * comment is reached or a non-comment partition.
+ *
+ * @param doc the document
+ * @param start the start of the backward search
+ * @param bound search boundary (exclusive)
+ * @return the comment start offset or -1
, if no suitable comment was found
+ * @throws BadLocationException
+ */
+ private static int searchCommentBackward(IDocument doc, int start, int bound) throws BadLocationException {
+ int firstLine= doc.getLineOfOffset(start);
+ if (firstLine == 0) {
+ return 0;
+ }
+ ITypedRegion partition= TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, start, true);
+ int currentOffset= Math.max(doc.getLineOffset(firstLine - 1), partition.getOffset() - 1);
+ int commentOffset= -1;
+ while (currentOffset > bound) {
+ partition= TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, currentOffset, true);
+ currentOffset= partition.getOffset() - 1;
+ if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())
+ || ICPartitions.C_MULTI_LINE_DOC_COMMENT.equals(partition.getType())) {
+ final int partitionOffset= partition.getOffset();
+ final int startLine= doc.getLineOfOffset(partitionOffset);
+ final int lineOffset= doc.getLineOffset(startLine);
+ if (partitionOffset == lineOffset ||
+ doc.get(lineOffset, partitionOffset - lineOffset).trim().length() == 0) {
+ return lineOffset;
+ }
+ return commentOffset;
+ } else if (ICPartitions.C_SINGLE_LINE_COMMENT.equals(partition.getType())
+ || ICPartitions.C_SINGLE_LINE_DOC_COMMENT.equals(partition.getType())) {
+ final int partitionOffset= partition.getOffset();
+ final int startLine= doc.getLineOfOffset(partitionOffset);
+ final int lineOffset= doc.getLineOffset(startLine);
+ if (partitionOffset == lineOffset ||
+ doc.get(lineOffset, partitionOffset - lineOffset).trim().length() == 0) {
+ commentOffset= lineOffset;
+ continue;
+ }
+ return commentOffset;
+ } else if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) {
+ if (doc.get(partition.getOffset(), partition.getLength()).trim().length() == 0) {
+ continue;
+ }
+ if (commentOffset >= 0) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ return commentOffset;
+ }
+ /**
+ * Determine if the name is part of a KnR function definition.
+ * @param name
+ * @return true
if the name is part of a KnR function
+ */
+ private boolean isKnRSource(IName name) {
+ if (name instanceof IASTName) {
+ IASTNode node= (IASTNode)name;
+ while (node.getParent() != null) {
+ if (node instanceof ICASTKnRFunctionDeclarator) {
+ return node.getParent() instanceof IASTFunctionDefinition;
+ }
+ node= node.getParent();
+ }
+ }
+ return false;
+ }
+ private int computeSourceStart(IDocument doc, int nameOffset, IBinding binding, boolean isKnR) throws BadLocationException {
+ int sourceStart= nameOffset;
+ CHeuristicScanner scanner= new CHeuristicScanner(doc);
+ if (binding instanceof IParameter) {
+ if (isKnR) {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { ')', ';' });
+ } else {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { '>', '(', ',' });
+ if (sourceStart > 0 && doc.getChar(sourceStart) == '>') {
+ sourceStart= scanner.findOpeningPeer(sourceStart - 1, '<', '>');
+ if (sourceStart > 0) {
+ sourceStart= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '(', ',' });
+ }
+ }
+ }
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return sourceStart;
+ }
+ sourceStart= scanner.findNonWhitespaceForward(sourceStart + 1, nameOffset);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ sourceStart = nameOffset;
+ }
+ } else if (binding instanceof ICPPTemplateParameter) {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { '>', '<', ',' });
+ if (sourceStart > 0 && doc.getChar(sourceStart) == '>') {
+ sourceStart= scanner.findOpeningPeer(sourceStart - 1, '<', '>');
+ if (sourceStart > 0) {
+ sourceStart= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '<', ',' });
+ }
+ }
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return sourceStart;
+ }
+ sourceStart= scanner.findNonWhitespaceForward(sourceStart + 1, nameOffset);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ sourceStart = nameOffset;
+ }
+ } else if (binding instanceof IEnumerator) {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { '{', ',' });
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return sourceStart;
+ }
+ sourceStart= scanner.findNonWhitespaceForward(sourceStart + 1, nameOffset);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ sourceStart = nameOffset;
+ }
+ } else {
+ final boolean expectClosingBrace;
+ IType type= null;
+ try {
+ if (binding instanceof ITypedef) {
+ type= ((ITypedef)binding).getType();
+ } else if (binding instanceof IVariable) {
+ type= ((IVariable)binding).getType();
+ }
+ } catch (Exception exc) {
+ }
+ expectClosingBrace= type instanceof ICompositeType || type instanceof IEnumeration;
+ final int nameLine= doc.getLineOfOffset(nameOffset);
+ sourceStart= nameOffset;
+ int commentBound;
+ if (isKnR) {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { ')', ';' });
+ } else {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '{', '}', ';' });
+ }
+ while (expectClosingBrace && commentBound > 0 && doc.getChar(commentBound) == '}') {
+ int openingBrace= scanner.findOpeningPeer(commentBound - 1, '{', '}');
+ if (openingBrace != CHeuristicScanner.NOT_FOUND) {
+ sourceStart= openingBrace - 1;
+ }
+ if (isKnR) {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { ')', ';' });
+ } else {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '{', '}', ';' });
+ }
+ }
+ if (commentBound == CHeuristicScanner.NOT_FOUND) {
+ commentBound= -1; // unbound
+ }
+ sourceStart= Math.min(sourceStart, doc.getLineOffset(nameLine));
+ int commentStart= searchCommentBackward(doc, sourceStart, commentBound);
+ if (commentStart >= 0) {
+ sourceStart= commentStart;
+ } else {
+ int nextNonWS= scanner.findNonWhitespaceForward(commentBound+1, sourceStart);
+ if (nextNonWS != CHeuristicScanner.NOT_FOUND) {
+ int nextNonWSLine= doc.getLineOfOffset(nextNonWS);
+ int lineOffset= doc.getLineOffset(nextNonWSLine);
+ if (doc.get(lineOffset, nextNonWS - lineOffset).trim().length() == 0) {
+ sourceStart= doc.getLineOffset(nextNonWSLine);
+ }
+ }
+ }
+ }
+ return sourceStart;
+ }
+ private int computeSourceEnd(IDocument doc, int start, IBinding binding, boolean isDefinition, boolean isKnR) throws BadLocationException {
+ int sourceEnd= start;
+ CHeuristicScanner scanner= new CHeuristicScanner(doc);
+ // expand forward to the end of the definition/declaration
+ boolean searchBrace= false;
+ boolean searchSemi= false;
+ boolean searchComma= false;
+ if (binding instanceof ICompositeType || binding instanceof IEnumeration) {
+ searchBrace= true;
+ } else if (binding instanceof ICPPTemplateDefinition) {
+ searchBrace= true;
+ } else if (binding instanceof IFunction && isDefinition) {
+ searchBrace= true;
+ } else if (binding instanceof IParameter) {
+ if (isKnR) {
+ searchSemi= true;
+ } else {
+ searchComma= true;
+ }
+ } else if (binding instanceof IEnumerator || binding instanceof ICPPTemplateParameter) {
+ searchComma= true;
+ } else if (binding instanceof IVariable || binding instanceof ITypedef) {
+ searchSemi= true;
+ } else if (!isDefinition) {
+ searchSemi= true;
+ }
+ if (searchBrace) {
+ int brace= scanner.scanForward(start, CHeuristicScanner.UNBOUND, '{');
+ if (brace != CHeuristicScanner.NOT_FOUND) {
+ sourceEnd= scanner.findClosingPeer(brace + 1, '{', '}');
+ if (sourceEnd == CHeuristicScanner.NOT_FOUND) {
+ sourceEnd= doc.getLength();
+ }
+ }
+ // expand region to include whole line
+ IRegion lineRegion= doc.getLineInformationOfOffset(sourceEnd);
+ sourceEnd= lineRegion.getOffset() + lineRegion.getLength();
+ } else if (searchSemi) {
+ int semi= scanner.scanForward(start, CHeuristicScanner.UNBOUND, ';');
+ if (semi != CHeuristicScanner.NOT_FOUND) {
+ sourceEnd= semi+1;
+ }
+ // expand region to include whole line
+ IRegion lineRegion= doc.getLineInformationOfOffset(sourceEnd);
+ sourceEnd= lineRegion.getOffset() + lineRegion.getLength();
+ } else if (searchComma) {
+ int bound;
+ if (binding instanceof IParameter) {
+ bound= scanner.findClosingPeer(start, '(', ')');
+ } else if (binding instanceof ICPPTemplateParameter) {
+ bound= scanner.findClosingPeer(start, '<', '>');
+ } else if (binding instanceof IEnumerator) {
+ bound= scanner.findClosingPeer(start, '{', '}');
+ } else {
+ bound = CHeuristicScanner.NOT_FOUND;
+ }
+ if (bound == CHeuristicScanner.NOT_FOUND) {
+ bound= Math.min(doc.getLength(), start + 100);
+ }
+ int comma= scanner.scanForward(start, bound, ',');
+ if (comma == CHeuristicScanner.NOT_FOUND) {
+ // last argument
+ sourceEnd= bound;
+ } else {
+ sourceEnd= comma;
+ // expand region to include whole line if rest is comment
+ IRegion lineRegion= doc.getLineInformationOfOffset(sourceEnd);
+ int lineEnd= lineRegion.getOffset() + lineRegion.getLength();
+ int nextNonWS= scanner.findNonWhitespaceForwardInAnyPartition(sourceEnd + 1, lineEnd);
+ if (nextNonWS != CHeuristicScanner.NOT_FOUND) {
+ String contentType= TextUtilities.getContentType(doc, ICPartitions.C_PARTITIONING, nextNonWS, false);
+ if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType) || ICPartitions.C_SINGLE_LINE_COMMENT.equals(contentType)) {
+ sourceEnd= lineEnd;
+ }
+ }
+ }
+ }
+ return sourceEnd;
+ }
+ /**
+ * Test whether the invocation offset is inside or before the preprocessor directive keyword.
+ *
+ * @param context
+ * the invocation context
+ * @return true
if the invocation offset is inside or before the directive keyword
+ */
+ private boolean inPreprocessorKeyword(CContentAssistInvocationContext context) {
+ IDocument doc = context.getDocument();
+ int offset = context.getInvocationOffset();
+
+ try {
+ final ITypedRegion partition = TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, offset, true);
+ if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
+ String ppPrefix = doc.get(partition.getOffset(), offset - partition.getOffset());
+ if (ppPrefix.matches("\\s*#\\s*\\w*")) { //$NON-NLS-1$
+ // we are inside the directive keyword
+ return true;
+ }
+ }
+
+ } catch (BadLocationException exc) {
+ }
+ return false;
+ }
+
+ /**
+ * Check if the invocation offset is inside a preprocessor directive.
+ *
+ * @param context
+ * the content asist invocation context
+ * @return true
if invocation offset is inside a preprocessor directive
+ */
+ private boolean inPreprocessorDirective(CContentAssistInvocationContext context) {
+ IDocument doc = context.getDocument();
+ int offset = context.getInvocationOffset();
+
+ try {
+ final ITypedRegion partition = TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, offset, true);
+ if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
+ return true;
+ }
+
+ } catch (BadLocationException exc) {
+ }
+ return false;
+ }
+
+ private void addMacroProposals(CContentAssistInvocationContext context, String prefix,
+ List
+b) in the case of each subsequent Contributor:Eclipse Foundation Software User Agreement
+Usage Of Content
+
+Applicable Licenses
+
+
+
+
+
+
+
+
+
+
+Use of Provisioning Technology
+
+
+
+
+Cryptography
+
+null
if none
+ * @return true
if this control is available
+ */
+ public static boolean isAvailable(Composite parent) {
+ if (!fgAvailabilityChecked) {
+ try {
+ Browser browser= new Browser(parent, SWT.NONE);
+ browser.dispose();
+ fgIsAvailable= true;
+
+ Slider sliderV= new Slider(parent, SWT.VERTICAL);
+ Slider sliderH= new Slider(parent, SWT.HORIZONTAL);
+ int width= sliderV.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+ int height= sliderH.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+ fgScrollBarSize= new Point(width, height);
+ sliderV.dispose();
+ sliderH.dispose();
+ } catch (SWTError er) {
+ fgIsAvailable= false;
+ } finally {
+ fgAvailabilityChecked= true;
+ }
+ }
+
+ return fgIsAvailable;
+ }
+
+ /**
+ * Minimal size constraints.
+ * @since 3.2
+ */
+ private static final int MIN_WIDTH= 80;
+
+ private static final int MIN_HEIGHT= 50;
+
+
+ /**
+ * Availability checking cache.
+ */
+ private static boolean fgIsAvailable= false;
+
+ private static boolean fgAvailabilityChecked= false;
+
+ /**
+ * Cached scroll bar width and height
+ * @since 3.4
+ */
+ private static Point fgScrollBarSize;
+
+ /** The control's browser widget */
+ private Browser fBrowser;
+
+ /** Tells whether the browser has content */
+ private boolean fBrowserHasContent;
+
+ /** Text layout used to approximate size of content when rendered in browser */
+ private TextLayout fTextLayout;
+
+ /** Bold text style */
+ private TextStyle fBoldStyle;
+
+ private BrowserInformationControlInput fInput;
+
+ /**
+ * true
iff the browser has completed loading of the last
+ * input set via {@link #setInformation(String)}.
+ * @since 3.4
+ */
+ private boolean fCompleted= false;
+
+ /**
+ * The listener to be notified when a delayed location changing event happened.
+ * @since 3.4
+ */
+ private IInputChangedListener fDelayedInputChangeListener;
+
+ /**
+ * The listeners to be notified when the input changed.
+ * @since 3.4
+ */
+ private ListenerList/*null
to use dialog font.
+ * @since 3.4
+ */
+ private final String fSymbolicFontName;
+
+
+ /**
+ * Creates a browser information control with the given shell as parent.
+ *
+ * @param parent the parent shell
+ * @param symbolicFontName the symbolic name of the font used for size computations
+ * @param resizable true
if the control should be resizable
+ * @since 3.4
+ */
+ public CDocBrowserInformationControl(Shell parent, String symbolicFontName, boolean resizable) {
+ super(parent, resizable);
+ fSymbolicFontName= symbolicFontName;
+ create();
+ }
+
+ /**
+ * Creates a browser information control with the given shell as parent.
+ *
+ * @param parent the parent shell
+ * @param symbolicFontName the symbolic name of the font used for size computations
+ * @param statusFieldText the text to be used in the optional status field
+ * or null
if the status field should be hidden
+ * @since 3.4
+ */
+ public CDocBrowserInformationControl(Shell parent, String symbolicFontName, String statusFieldText) {
+ super(parent, statusFieldText);
+ fSymbolicFontName= symbolicFontName;
+ create();
+ }
+
+ /**
+ * Creates a browser information control with the given shell as parent.
+ *
+ * @param parent the parent shell
+ * @param symbolicFontName the symbolic name of the font used for size computations
+ * @param toolBarManager the manager or null
if toolbar is not desired
+ * @since 3.4
+ */
+ public CDocBrowserInformationControl(Shell parent, String symbolicFontName, ToolBarManager toolBarManager) {
+ super(parent, toolBarManager);
+ fSymbolicFontName= symbolicFontName;
+ create();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControl#createContent(org.eclipse.swt.widgets.Composite)
+ */
+ protected void createContent(Composite parent) {
+ fBrowser= new Browser(parent, SWT.NONE);
+ fBrowser.setJavascriptEnabled(false);
+
+ Display display= getShell().getDisplay();
+ fBrowser.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ fBrowser.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ fBrowser.addProgressListener(new ProgressAdapter() {
+ public void completed(ProgressEvent event) {
+ fCompleted= true;
+ }
+ });
+
+ fBrowser.addOpenWindowListener(new OpenWindowListener() {
+ public void open(WindowEvent event) {
+ event.required= true; // Cancel opening of new windows
+ }
+ });
+
+ // Replace browser's built-in context menu with none
+ fBrowser.setMenu(new Menu(getShell(), SWT.NONE));
+
+ createTextLayout();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @deprecated use {@link #setInput(Object)}
+ */
+ public void setInformation(final String content) {
+ setInput(new BrowserInformationControlInput(null) {
+ public String getHtml() {
+ return content;
+ }
+
+ public String getInputName() {
+ return ""; //$NON-NLS-1$
+ }
+
+ public Object getInputElement() {
+ return content;
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc} This control can handle {@link String} and
+ * {@link BrowserInformationControlInput}.
+ */
+ public void setInput(Object input) {
+ Assert.isLegal(input == null || input instanceof String || input instanceof BrowserInformationControlInput);
+
+ if (input instanceof String) {
+ setInformation((String)input);
+ return;
+ }
+
+ fInput= (BrowserInformationControlInput)input;
+
+ String content= null;
+ if (fInput != null)
+ content= fInput.getHtml();
+
+ fBrowserHasContent= content != null && content.length() > 0;
+
+ if (!fBrowserHasContent)
+ content= ""; //$NON-NLS-1$
+
+ boolean RTL= (getShell().getStyle() & SWT.RIGHT_TO_LEFT) != 0;
+ boolean resizable= isResizable();
+
+ // The default "overflow:auto" would not result in a predictable width for the client area
+ // and the re-wrapping would cause visual noise
+ String[] styles= null;
+ if (RTL && resizable)
+ styles= new String[] { "direction:rtl;", "overflow:scroll;", "word-wrap:break-word;" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ else if (RTL && !resizable)
+ styles= new String[] { "direction:rtl;", "overflow:hidden;", "word-wrap:break-word;" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ else if (!resizable)
+ //XXX: In IE, "word-wrap: break-word;" causes bogus wrapping even in non-broken words :-(see e.g. Javadoc of String).
+ // Re-check whether we really still need this now that the Javadoc Hover header already sets this style.
+ styles= new String[] { "overflow:hidden;"/*, "word-wrap: break-word;"*/}; //$NON-NLS-1$
+ else
+ styles= new String[] { "overflow:scroll;" }; //$NON-NLS-1$
+
+ StringBuffer buffer= new StringBuffer(content);
+ HTMLPrinter.insertStyles(buffer, styles);
+ content= buffer.toString();
+
+ /*
+ * XXX: Should add some JavaScript here that shows something like
+ * "(continued...)" or "..." at the end of the visible area when the page overflowed
+ * with "overflow:hidden;".
+ */
+
+ fCompleted= false;
+ if (!content.contains(".html")) {
+ return;
+ }
+ String url = CUIPreferenceInitializer.doxygenDirectoryPath + "/" + content;
+ CElementLinks.isSet = 1;
+ fBrowser.setUrl(url);
+
+ Object[] listeners= fInputChangeListeners.getListeners();
+ for (int i= 0; i < listeners.length; i++)
+ ((IInputChangedListener)listeners[i]).inputChanged(fInput);
+ }
+
+ /*
+ * @see IInformationControl#setVisible(boolean)
+ */
+ public void setVisible(boolean visible) {
+ Shell shell= getShell();
+ if (shell.isVisible() == visible)
+ return;
+
+ if (!visible) {
+ super.setVisible(false);
+ setInput(null);
+ return;
+ }
+
+ /*
+ * The Browser widget flickers when made visible while it is not completely loaded.
+ * The fix is to delay the call to setVisible until either loading is completed
+ * (see ProgressListener in constructor), or a timeout has been reached.
+ */
+ final Display display= shell.getDisplay();
+
+ // Make sure the display wakes from sleep after timeout:
+ display.timerExec(100, new Runnable() {
+ public void run() {
+ fCompleted= true;
+ }
+ });
+
+ while (!fCompleted) {
+ // Drive the event loop to process the events required to load the browser widget's contents:
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ shell= getShell();
+ if (shell == null || shell.isDisposed())
+ return;
+
+ /*
+ * Avoids flickering when replacing hovers, especially on Vista in ON_CLICK mode.
+ * Causes flickering on GTK. Carbon does not care.
+ */
+ if ("win32".equals(SWT.getPlatform())) //$NON-NLS-1$
+ shell.moveAbove(null);
+
+ super.setVisible(true);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControl#setSize(int, int)
+ */
+ public void setSize(int width, int height) {
+ fBrowser.setRedraw(false); // avoid flickering
+ try {
+ //super.setSize(width, height);
+ super.setSize(750, 300); // TODO Modify
+ } finally {
+ fBrowser.setRedraw(true);
+ }
+ }
+
+ /**
+ * Creates and initializes the text layout used
+ * to compute the size hint.
+ *
+ * @since 3.2
+ */
+ private void createTextLayout() {
+ fTextLayout= new TextLayout(fBrowser.getDisplay());
+
+ // Initialize fonts
+ String symbolicFontName= fSymbolicFontName == null ? JFaceResources.DIALOG_FONT : fSymbolicFontName;
+ Font font= JFaceResources.getFont(symbolicFontName);
+ fTextLayout.setFont(font);
+ fTextLayout.setWidth(-1);
+ font= JFaceResources.getFontRegistry().getBold(symbolicFontName);
+ fBoldStyle= new TextStyle(font, null, null);
+
+ // Compute and set tab width
+ fTextLayout.setText(" "); //$NON-NLS-1$
+ int tabWidth= fTextLayout.getBounds().width;
+ fTextLayout.setTabs(new int[] { tabWidth });
+ fTextLayout.setText(""); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.text.AbstractInformationControl#handleDispose()
+ * @since 3.6
+ */
+ protected void handleDispose() {
+ if (fTextLayout != null) {
+ fTextLayout.dispose();
+ fTextLayout= null;
+ }
+ fBrowser= null;
+
+ super.handleDispose();
+ }
+
+ /*
+ * @see IInformationControl#computeSizeHint()
+ */
+ public Point computeSizeHint() {
+ Point sizeConstraints= getSizeConstraints();
+ Rectangle trim= computeTrim();
+ int height= trim.height;
+
+ //FIXME: The HTML2TextReader does not render true
iff a delayed input change
+ * listener is currently registered
+ * @since 3.4
+ */
+ public boolean hasDelayedInputChangeListener() {
+ return fDelayedInputChangeListener != null;
+ }
+
+ /**
+ * Notifies listeners of a delayed input change.
+ *
+ * @param newInput the new input, or null
to request cancellation
+ * @since 3.4
+ */
+ public void notifyDelayedInputChange(Object newInput) {
+ if (fDelayedInputChangeListener != null)
+ fDelayedInputChangeListener.inputChanged(newInput);
+ }
+
+ /*
+ * @see java.lang.Object#toString()
+ * @since 3.4
+ */
+ public String toString() {
+ String style= (getShell().getStyle() & SWT.RESIZE) == 0 ? "fixed" : "resizeable"; //$NON-NLS-1$ //$NON-NLS-2$
+ return super.toString() + " - style: " + style; //$NON-NLS-1$
+ }
+
+ /**
+ * @return the current browser input or null
+ */
+ public BrowserInformationControlInput getInput() {
+ return fInput;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension5#computeSizeConstraints(int, int)
+ */
+ public Point computeSizeConstraints(int widthInChars, int heightInChars) {
+ if (fSymbolicFontName == null)
+ return null;
+
+ GC gc= new GC(fBrowser);
+ Font font= fSymbolicFontName == null ? JFaceResources.getDialogFont() : JFaceResources.getFont(fSymbolicFontName);
+ gc.setFont(font);
+ int width= gc.getFontMetrics().getAverageCharWidth();
+ int height= gc.getFontMetrics().getHeight();
+ gc.dispose();
+
+ return new Point(widthInChars * width, heightInChars * height);
+ }
+}
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocBrowserInformationControlInput.java b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocBrowserInformationControlInput.java
new file mode 100644
index 0000000..3305a84
--- /dev/null
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocBrowserInformationControlInput.java
@@ -0,0 +1,66 @@
+package org.eclipse.cdt.internal.ui.text.c.hover;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.internal.text.html.BrowserInformationControlInput;
+
+/**
+ * Provides input for CDocBrowserInformationControl.
+ */
+public class CDocBrowserInformationControlInput extends BrowserInformationControlInput {
+ private final String fElement;
+ private final String fHtml;
+ private final int fLeadingImageWidth;
+
+ /**
+ * Creates a new browser information control input.
+ *
+ * @param previous previous input, or null
if none available
+ * @param element the element, or null
if none available
+ * @param html HTML contents, must not be null
+ * @param leadingImageWidth the indent required for the element image
+ */
+ public CDocBrowserInformationControlInput(CDocBrowserInformationControlInput previous, String element, String html, int leadingImageWidth) {
+ super(previous);
+ Assert.isNotNull(html);
+ fElement= element;
+ fHtml= html;
+ fLeadingImageWidth= leadingImageWidth;
+ }
+
+ /*
+ * @see org.eclipse.jface.internal.text.html.BrowserInformationControlInput#getLeadingImageWidth()
+ * @since 3.4
+ */
+ public int getLeadingImageWidth() {
+ return fLeadingImageWidth;
+ }
+
+ /**
+ * Returns the Java element.
+ *
+ * @return the element or null
if none available
+ */
+ public String getElement() {
+ return fElement;
+ }
+
+ @Override
+ public String getHtml() {
+ // TODO Auto-generated method stub
+ return fHtml;
+ }
+
+ @Override
+ public Object getInputElement() {
+ // TODO Auto-generated method stub
+ return fElement == null ? (Object) fHtml : fElement;
+ }
+
+ @Override
+ public String getInputName() {
+ // TODO Auto-generated method stub
+ //return fElement == null ? "" : fElement.getElementName(); //$NON-NLS-1$
+ return fElement == null ? "" : fElement;
+ }
+
+}
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocHover.java b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocHover.java
index e912220..34dc834 100644
--- a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocHover.java
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CDocHover.java
@@ -11,33 +11,992 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.c.hover;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Set;
+import java.util.StringTokenizer;
+import org.eclipse.cdt.core.dom.ast.DOMException;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ILanguage;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.core.parser.KeywordSetKey;
+import org.eclipse.cdt.core.parser.ParserFactory;
+import org.eclipse.cdt.core.parser.ParserLanguage;
+import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
+import org.eclipse.cdt.internal.corext.util.Strings;
+import org.eclipse.cdt.internal.ui.CHelpProviderManager;
+import org.eclipse.cdt.internal.ui.editor.ASTProvider;
+import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
+import org.eclipse.cdt.internal.ui.text.CWordFinder;
+import org.eclipse.cdt.internal.ui.text.HTMLPrinter;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.CUIPreferenceInitializer;
+import org.eclipse.cdt.ui.IFunctionSummary;
+import org.eclipse.cdt.ui.IFunctionSummary.IFunctionPrototypeSummary;
+import org.eclipse.cdt.ui.IRequiredInclude;
+import org.eclipse.cdt.ui.IWorkingCopyManager;
+import org.eclipse.cdt.ui.PreferenceConstants;
+import org.eclipse.cdt.ui.text.ICHelpInvocationContext;
+import org.eclipse.cdt.ui.text.IHoverHelpInvocationContext;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.internal.text.html.BrowserInformationControlInput;
+import org.eclipse.jface.internal.text.html.BrowserInput;
+import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlExtension4;
+import org.eclipse.jface.text.IInputChangedListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
+import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.cdt.ui.IFunctionSummary;
-import org.eclipse.cdt.ui.IRequiredInclude;
-import org.eclipse.cdt.ui.IFunctionSummary.IFunctionPrototypeSummary;
-import org.eclipse.cdt.ui.text.ICHelpInvocationContext;
-import org.eclipse.cdt.ui.text.IHoverHelpInvocationContext;
+/**
+ * Provides doxygen hover.
+ */
+public class CDocHover extends AbstractCEditorTextHover {
-import org.eclipse.cdt.internal.ui.CHelpProviderManager;
-import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
-import org.eclipse.cdt.internal.ui.text.CWordFinder;
-import org.eclipse.cdt.internal.ui.text.HTMLPrinter;
+ private static String doxygenDirectoryPath;
-public class CDocHover extends AbstractCEditorTextHover {
-
/**
* Constructor for DefaultCEditorTextHover
*/
public CDocHover() {
+ doxygenDirectoryPath = CUIPreferenceInitializer.doxygenDirectoryPath;
+ }
+
+ private static class SingletonRule implements ISchedulingRule {
+ public static final ISchedulingRule INSTANCE = new SingletonRule();
+ public boolean contains(ISchedulingRule rule) {
+ return rule == this;
+ }
+ public boolean isConflicting(ISchedulingRule rule) {
+ return rule == this;
+ }
+ }
+
+ /**
+ * Computes the source location for a given identifier.
+ */
+ private static class ComputeSourceRunnable implements ASTRunnable {
+
+ private final IRegion fTextRegion;
+ private String fSource;
+
+ /**
+ * If method is in source file, this is used.
+ */
+ private final int methodInSource = 1001;
+ /**
+ * If method is in header file, this is used.
+ */
+ private final int methodInHeader = 1002;
+
+ public ComputeSourceRunnable(ITranslationUnit tUnit, IRegion textRegion) {
+ fTextRegion = textRegion;
+ fSource = null;
+ }
+
+ /**
+ * Tokenizer
+ *
+ * @param string string to tokenize
+ * @return array of tokenized string
+ */
+ private String[] tokenizeString(String string) {
+ StringTokenizer tokenizer = new StringTokenizer(string);
+ String tokenOfString[] = new String[tokenizer.countTokens()];
+ int index = 0;
+ while (tokenizer.hasMoreTokens()) {
+ tokenOfString[index] = tokenizer.nextToken();
+ index++;
+ }
+ return tokenOfString;
+ }
+ /**
+ * Tokenizer with delimiter
+ *
+ * @param string string to tokenize
+ * @param delimiter delimiter
+ * @return array of tokenized string
+ */
+ private String[] tokenizeStringWithDelimiter(String string, String delimiter) {
+ StringTokenizer tokenizer = new StringTokenizer(string, delimiter);
+ String tokenOfString[] = new String[tokenizer.countTokens()];
+ int index = 0;
+ while (tokenizer.hasMoreTokens()) {
+ tokenOfString[index] = tokenizer.nextToken();
+ index++;
+ }
+ return tokenOfString;
+ }
+ /**
+ * Check HTML file existence.
+ *
+ * @param htmlFileName HTML file name
+ * @return true if it exist, false if it doesn't exist
+ * @throws IOException if an I/O error has occurred
+ */
+ private boolean checkHTMLFileExistence(String htmlFileName) throws IOException {
+ File file = new File(doxygenDirectoryPath);
+ File fileList[] = file.listFiles();
+ for (int i = 0; i < fileList.length; i++) {
+ if (htmlFileName.equals(fileList[i].getName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ /**
+ * Find location of member variable of class.
+ *
+ * @param htmlLine 1 line of HTML file
+ * @param memberName method name
+ * @return location of member variable of class n HTML file
+ */
+ private String searchMemberVariableLocationOfCalss(String htmlLine, String memberName) {
+ String tempString = null;
+ String htmlFile = null;
+ if (htmlLine.contains("class=\"memlist\"") == true) {
+ tempString = htmlLine.trim();
+ tempString = htmlLine.substring( htmlLine.indexOf(">", htmlLine.indexOf("href")) + 1, htmlLine.length());
+ if (tempString.indexOf(memberName) == 0) {
+ htmlFile = htmlLine.substring(htmlLine.indexOf("href") + 6, htmlLine.indexOf("\"", htmlLine.indexOf("href") + 6));
+ return htmlFile;
+ }
+ }
+ return null;
+ }
+ /**
+ * Change string with enumeration brace.
+ *
+ * @param str string with enumeration brace
+ * @return changed string
+ */
+ private String changeStringWithEnumerationBrace(String str) {
+ StringBuilder sb = new StringBuilder(str);
+ int index = 0;
+ int index2 = 0;
+ while (index != 4) {
+ index = sb.indexOf("enum {", index) + 5;
+ index2 = sb.indexOf("}", index);
+ if ((index2 != -1) && (index != -1)) {
+ sb.delete(index2, index2 + 1);
+ sb.delete(index, index + 1);
+ }
+ }
+ return sb.toString();
+ }
+ /**
+ * Change string with void.
+ *
+ * @param str string with void
+ * @return changed string
+ */
+ private String changeStringWithVoid(String str) {
+ StringBuilder sb = new StringBuilder(str);
+ int index = 0;
+ int index2 = 0;
+ while (index != -1) {
+ index = sb.indexOf("(void)", index);
+ index2 = index + 5;
+ if ((index2 != -1) && (index != -1)) {
+ sb.delete(index2, index2 + 1);
+ sb.delete(index, index + 1);
+ }
+ }
+ return sb.toString();
+ }
+ /**
+ * Change string with template.
+ *
+ * @param str string with template
+ * @return changed string
+ */
+ private String changeStringWithTemplate(String str) {
+ StringBuilder sb = new StringBuilder(str);
+ String type = str.substring(str.indexOf("<") + 1, str.indexOf(">"));
+ if (!type.contains(",")) {
+ str = str.replaceAll(type, "");
+ return str;
+ } else if (type.contains(",")) {
+ sb.replace(sb.indexOf("<") + 1, sb.indexOf(",", sb.indexOf("<")), "");
+ sb.replace(sb.indexOf(",", sb.indexOf("<")) + 1, sb.indexOf(">"), "");
+ return sb.toString();
+ }
+ return null;
+ }
+ /**
+ * Change string with asterisk.
+ *
+ * @param str string with asterisk
+ * @return changed string
+ */
+ private String changeStringWithAsterisk(String str) {
+ StringBuilder sb = new StringBuilder(str);
+ int index = 0;
+ while (index != -1) {
+ index = sb.indexOf("*", index);
+ if (index != -1) {
+ sb.delete(index, index + 1);
+ sb.replace(index - 1, index, "* ");
+ }
+ }
+
+ return sb.toString();
+ }
+ /**
+ * Find location of method of class in HTML file.
+ *
+ * @param htmlLine 1 line of HTML file
+ * @param binding IBinding
+ * @param isWhere methodInSource if method is in source file, methodInHeader if method is in header file
+ * @param isMethodOfClass true if method of class, false if method of interface
+ * @return location of method of class in HTML file
+ * @throws DOMException
+ */
+ private String searchMethodLocationOfClass(String htmlLine, IBinding binding, int isWhere, boolean isMethodOfClass) throws DOMException {
+ String htmlFile = null;
+
+ String str[] = tokenizeString(binding.toString());
+ if (str.length == 2) {
+ if (str[1].equals("CPPFIELD")) {
+ if ( (htmlFile = searchMemberVariableLocationOfCalss(htmlLine, str[0])) != null) {
+ return htmlFile;
+ }
+ }
+ }
+
+ String bindingString = binding.toString();
+ if (bindingString.contains("long int")) {
+ bindingString = bindingString.replaceAll("long int", "long");
+ }
+ if (bindingString.contains("short int")) {
+ bindingString = bindingString.replaceAll("short int", "short");
+ }
+ if (bindingString.contains("enum {")) {
+ bindingString = changeStringWithEnumerationBrace(bindingString);
+ }
+ if (bindingString.contains("enum ")) {
+ bindingString = bindingString.replaceAll("enum ", "");
+ }
+ /* handling defined type start */
+ if (bindingString.contains("wchar_t")) {
+ bindingString = bindingString.replaceAll("wchar_t", "mchar");
+ }
+ if (bindingString.contains("Buffernull
, if no source could be computed
+ */
+ public String getSource() {
+ return fSource;
+ }
+
}
/* (non-Javadoc)
@@ -120,6 +1079,125 @@ public class CDocHover extends AbstractCEditorTextHover {
return null;
}
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ @Override
+ public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
+ IEditorPart editor = getEditor();
+ if (editor != null) {
+ IEditorInput input = editor.getEditorInput();
+ IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager();
+ IWorkingCopy copy = manager.getWorkingCopy(input);
+ try {
+ if (copy == null || !copy.isConsistent()) {
+ return null;
+ }
+ } catch (CModelException exc) {
+ return null;
+ }
+
+ String expression;
+ try {
+ expression = textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength());
+ expression = expression.trim();
+ if (expression.length() == 0)
+ return null;
+
+ //Before trying a search lets make sure that the user is not hovering over a keyword
+ if (selectionIsKeyword(expression))
+ return null;
+
+ String source = null;
+
+ // Try with the indexer
+ source= searchInIndex(copy, hoverRegion);
+
+ if (source == null || source.trim().length() == 0)
+ return null;
+
+ if (!source.contains(".html")) {
+ return null;
+ }
+
+ // we are actually interested in the comments, too.
+ //source= removeLeadingComments(source);
+
+ String delim= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ String[] sourceLines = Strings.convertIntoLines(source);
+ String firstLine = sourceLines[0];
+ if (!Character.isWhitespace(firstLine.charAt(0)))
+ sourceLines[0] = ""; //$NON-NLS-1$
+ Strings.trimIndentation(sourceLines, getTabWidth(), getTabWidth());
+
+ if (!Character.isWhitespace(firstLine.charAt(0)))
+ sourceLines[0] = firstLine;
+
+ source = Strings.concatenate(sourceLines, delim);
+
+ return internalGetHoverInfo(source, hoverRegion);
+ } catch (BadLocationException e) {
+ }
+ }
+ return null;
+ }
+
+ private CDocBrowserInformationControlInput internalGetHoverInfo(String elements, IRegion hoverRegion) {
+ return getHoverInfo(elements, null, hoverRegion, null);
+ }
+
+ private static CDocBrowserInformationControlInput getHoverInfo(String elements, String editorInputElement, IRegion hoverRegion, CDocBrowserInformationControlInput previousInput) {
+ int leadingImageWidth = 20;
+ return new CDocBrowserInformationControlInput(previousInput, elements, elements, leadingImageWidth);
+ }
+
+ private static int getTabWidth() {
+ return 4;
+ }
+
+ private String searchInIndex(final ITranslationUnit tUnit, IRegion textRegion) {
+ final ComputeSourceRunnable computer= new ComputeSourceRunnable(tUnit, textRegion);
+ Job job= new Job(CHoverMessages.CSourceHover_jobTitle) {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ return ASTProvider.getASTProvider().runOnAST(tUnit, ASTProvider.WAIT_ACTIVE_ONLY, monitor, computer);
+ } catch (Throwable t) {
+ CUIPlugin.log(t);
+ }
+ return Status.CANCEL_STATUS;
+ }
+ };
+ // If the hover thread is interrupted this might have negative
+ // effects on the index - see http://bugs.eclipse.org/219834
+ // Therefore we schedule a job to decouple the parsing from this thread.
+ job.setPriority(Job.DECORATE);
+ job.setSystem(true);
+ job.setRule(SingletonRule.INSTANCE);
+ job.schedule();
+ try {
+ job.join();
+ } catch (InterruptedException exc) {
+ job.cancel();
+ return null;
+ }
+ return computer.getSource();
+ }
+
+
+ /**
+ * Test whether the given name is a known keyword.
+ *
+ * @param name
+ * @return true
if the name is a known keyword or false
if the
+ * name is not considered a keyword
+ */
+ private boolean selectionIsKeyword(String name) {
+ Setnull
if none
+ * @since 3.6
+ */
+ public PresenterControlCreator(IWorkbenchSite site) {
+ fSite = site;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#doCreateInformationControl(org.eclipse.swt.widgets.Shell)
+ */
+ public IInformationControl doCreateInformationControl(Shell parent) {
+ if (CDocBrowserInformationControl.isAvailable(parent)) {
+ ToolBarManager tbm = new ToolBarManager(SWT.FLAT);
+ String font = PreferenceConstants.EDITOR_TEXT_FONT;
+ CDocBrowserInformationControl iControl = new CDocBrowserInformationControl(parent, font, tbm);
+
+ final BackAction backAction = new BackAction(iControl);
+ backAction.setEnabled(false);
+ tbm.add(backAction);
+ final ForwardAction forwardAction = new ForwardAction(iControl);
+ tbm.add(forwardAction);
+ forwardAction.setEnabled(false);
+
+ IInputChangedListener inputChangeListener= new IInputChangedListener() {
+ public void inputChanged(Object newInput) {
+ backAction.update();
+ forwardAction.update();
+ }
+ };
+ iControl.addInputChangeListener(inputChangeListener);
+
+ tbm.update(true);
+
+ addLinkListener(iControl);
+ return iControl;
+
+ } else {
+ return new DefaultInformationControl(parent, true);
+ }
+ }
+ }
+
+ /**
+ * Hover control creator.
+ *
+ * @since 3.3
+ */
+ public static final class HoverControlCreator extends AbstractReusableInformationControlCreator {
+ /**
+ * The information presenter control creator.
+ * @since 3.4
+ */
+ private final IInformationControlCreator fInformationPresenterControlCreator;
+ /**
+ * true
to use the additional info affordance, false
to use the hover affordance.
+ */
+ private final boolean fAdditionalInfoAffordance;
+
+ /**
+ * @param informationPresenterControlCreator control creator for enriched hover
+ * @since 3.4
+ */
+ public HoverControlCreator(IInformationControlCreator informationPresenterControlCreator) {
+ this(informationPresenterControlCreator, false);
+ }
+
+ /**
+ * @param informationPresenterControlCreator control creator for enriched hover
+ * @param additionalInfoAffordance true
to use the additional info affordance, false
to use the hover affordance
+ * @since 3.4
+ */
+ public HoverControlCreator(IInformationControlCreator informationPresenterControlCreator, boolean additionalInfoAffordance) {
+ fInformationPresenterControlCreator = informationPresenterControlCreator;
+ fAdditionalInfoAffordance = additionalInfoAffordance;
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#doCreateInformationControl(org.eclipse.swt.widgets.Shell)
+ */
+ public IInformationControl doCreateInformationControl(Shell parent) {
+ String tooltipAffordanceString = fAdditionalInfoAffordance ? "showTextHoverAffordance" : EditorsUI.getTooltipAffordanceString();
+ if (CDocBrowserInformationControl.isAvailable(parent)) {
+ String font= PreferenceConstants.EDITOR_TEXT_FONT;
+ CDocBrowserInformationControl iControl = new CDocBrowserInformationControl(parent, font, tooltipAffordanceString) {
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension5#getInformationPresenterControlCreator()
+ */
+ public IInformationControlCreator getInformationPresenterControlCreator() {
+ return fInformationPresenterControlCreator;
+ }
+ };
+ addLinkListener(iControl);
+ return iControl;
+ } else {
+ return new DefaultInformationControl(parent, tooltipAffordanceString);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#canReuse(org.eclipse.jface.text.IInformationControl)
+ */
+ public boolean canReuse(IInformationControl control) {
+ if (!super.canReuse(control))
+ return false;
+
+ if (control instanceof IInformationControlExtension4) {
+ String tooltipAffordanceString = fAdditionalInfoAffordance ? "showTextHoverAffordance" : EditorsUI.getTooltipAffordanceString();
+ ((IInformationControlExtension4)control).setStatusText(tooltipAffordanceString);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * The hover control creator.
+ *
+ * @since 3.2
+ */
+ private IInformationControlCreator fHoverControlCreator;
+ /**
+ * The presentation control creator.
+ *
+ * @since 3.2
+ */
+ private IInformationControlCreator fPresenterControlCreator;
}
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CElementLinks.java b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CElementLinks.java
new file mode 100644
index 0000000..4430dc1
--- /dev/null
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CElementLinks.java
@@ -0,0 +1,100 @@
+package org.eclipse.cdt.internal.ui.text.c.hover;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.LocationAdapter;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.browser.LocationListener;
+
+/**
+ * Links inside doxygen hovers.
+ */
+public class CElementLinks {
+ /**
+ * A handler is asked to handle links to targets.
+ */
+ public interface ILinkHandler {
+
+ /**
+ * Handle normal kind of link to given target.
+ *
+ * @param target the target to show
+ */
+ void handleInlineCDocLink(String target);
+
+ /**
+ * Informs the handler that the text of the browser was set.
+ */
+ void handleTextSet();
+ }
+
+ public static final String CDOC_SCHEME= "file"; //$NON-NLS-1$
+ public static int isSet = 0;
+
+ private CElementLinks() {
+ // static only
+ }
+
+ /**
+ * Creates a location listener which uses the given handler
+ * to handle java element links.
+ *
+ * The location listener can be attached to a {@link Browser}
+ *
+ * @param handler the handler to use to handle links
+ * @return a new {@link LocationListener}
+ */
+ public static LocationListener createLocationListener(final ILinkHandler handler) {
+ return new LocationAdapter() {
+ public void changing(LocationEvent event) {
+ String loc = event.location;
+ if (CElementLinks.isSet == 1) {
+ CElementLinks.isSet = 0;
+ return;
+ }
+
+ if ("about:blank".equals(loc)) { //$NON-NLS-1$
+ /*
+ * Using the Browser.setText API triggers a location change to "about:blank".
+ * XXX: remove this code once https://bugs.eclipse.org/bugs/show_bug.cgi?id=130314 is fixed
+ */
+ //input set with setText
+ handler.handleTextSet();
+ return;
+ }
+
+ event.doit= false;
+
+ if (loc.startsWith("about:")) { //$NON-NLS-1$
+ // Relative links should be handled via head > base tag.
+ // If no base is available, links just won't work.
+ return;
+ }
+
+ URI uri;
+ try {
+ uri= new URI(loc);
+ } catch (URISyntaxException e) {
+ // try it with a file (workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=237903 ):
+ File file= new File(loc);
+ if (!file.exists()) {
+ //JavaPlugin.log(e);
+ return;
+ }
+ uri = file.toURI();
+ loc = uri.toASCIIString();
+ }
+
+ String scheme = uri.getScheme();
+ if (CElementLinks.CDOC_SCHEME.equals(scheme)) {
+ String uriString = uri.toString();
+ handler.handleInlineCDocLink(uriString.substring(uriString.lastIndexOf("/") + 1, uriString.length()));
+ event.doit= true;
+ }
+ }
+ };
+ }
+}
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java
index 9838be3..6f63c01 100644
--- a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java
@@ -33,6 +33,9 @@ public final class CHoverMessages extends NLS {
public static String CSourceHover_jobTitle;
+ public static String CDocHover_back;
+ public static String CDocHover_forward;
+
static {
NLS.initializeMessages(CHoverMessages.class.getName(), CHoverMessages.class);
}
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties
index cb14e7a..b44e269 100644
--- a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties
@@ -26,3 +26,6 @@ CMacroExpansionControl_title_original=Original
CMacroExpansionInput_jobTitle= Computing Macro Expansion
CSourceHover_jobTitle= Computing Source
+
+CDocHover_back=Back
+CDocHover_forward=Forward
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java
index 969caba..ced0020 100644
--- a/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java
@@ -17,25 +17,24 @@ package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.List;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.ITypedRegion;
-import org.eclipse.jface.text.TextUtilities;
-import org.eclipse.jface.text.contentassist.ICompletionProposal;
-import org.eclipse.swt.graphics.Image;
-
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IPositionConverter;
+import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
@@ -43,7 +42,9 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
+import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
+import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
@@ -62,13 +63,18 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
+import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.index.IIndexName;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
-import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.cdt.ui.text.ICPartitions;
-
import org.eclipse.cdt.internal.core.dom.parser.c.CBuiltinParameter;
import org.eclipse.cdt.internal.core.dom.parser.c.CBuiltinVariable;
import org.eclipse.cdt.internal.core.dom.parser.c.CImplicitFunction;
@@ -80,8 +86,36 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitTypedef;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.AccessContext;
import org.eclipse.cdt.internal.core.parser.util.ContentAssistMatcherFactory;
-
+import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
+import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.IWorkingCopyManager;
+import org.eclipse.cdt.ui.text.ICPartitions;
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+import org.eclipse.core.filebuffers.LocationKind;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
/**
* Searches the DOM (both the AST and the index) for completion proposals.
@@ -89,20 +123,42 @@ import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
* @author Bryan Wilkinson
*/
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
+ private final IProgressMonitor fMonitor;
+ private ITranslationUnit fTU;
/**
* Default constructor is required (executable extension).
*/
public DOMCompletionProposalComputer() {
+ fMonitor = new NullProgressMonitor();
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkingCopy copy = null;
+ if (window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+ IEditorPart editor = page.getActiveEditor();
+ if (editor != null) {
+ IEditorInput input = editor.getEditorInput();
+ IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager();
+ copy = manager.getWorkingCopy(input);
+ fTU = copy;
+ }
+ }
+ }
}
-
+
@Override
protected Listnull
, if no source could be computed
+ * @throws CoreException if the source file could not be loaded or if there was a
+ * problem with the index
+ */
+ private String computeSourceForBinding(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] names = findDefsOrDecls(ast, binding);
+
+ // in case the binding is a non-explicit specialization we need
+ // to consider the original binding (bug 281396)
+ if (names.length == 0 && binding instanceof ICPPSpecialization) {
+ binding= ((ICPPSpecialization) binding).getSpecializedBinding();
+ if (!(binding instanceof IProblemBinding)) {
+ names= findDefsOrDecls(ast, binding);
+ }
+ }
+ if (names.length > 0) {
+ for (IName name : names) {
+ String source= computeSourceForName(name, binding);
+ if (source != null) {
+ return source;
+ }
+ }
+ }
+ return null;
+ }
+ /**
+ * Search for definitions or declarations for the given binding.
+ * @param ast the AST of the translation unit
+ * @param binding the binding
+ * @return an array of definitions or declarations, never null
+ * @throws CoreException
+ */
+ private IName[] findDefsOrDecls(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] names= findDefinitions(ast, binding);
+ if (names.length == 0) {
+ names= findDeclarations(ast, binding);
+ }
+ return names;
+ }
+ /**
+ * Search for definitions for the given binding.
+ *
+ * @param ast the AST of the translation unit
+ * @param binding the binding
+ * @return an array of definitions, never null
+ * @throws CoreException
+ */
+ private IName[] findDefinitions(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] declNames= ast.getDefinitionsInAST(binding);
+ if (declNames.length == 0 && ast.getIndex() != null) {
+ // search definitions in index
+ declNames = ast.getIndex().findNames(binding, IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
+ }
+ return declNames;
+ }
+ /**
+ * Search for declarations for the given binding.
+ *
+ * @param ast the AST of the translation unit
+ * @param binding the binding
+ * @return an array of declarations, never null
+ * @throws CoreException
+ */
+ private IName[] findDeclarations(IASTTranslationUnit ast, IBinding binding) throws CoreException {
+ IName[] declNames= ast.getDeclarationsInAST(binding);
+ if (declNames.length == 0 && ast.getIndex() != null) {
+ // search declarations in index
+ declNames= ast.getIndex().findNames(binding, IIndex.FIND_DECLARATIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
+ }
+ return declNames;
+ }
+ /**
+ * Get the source for the given name from the underlying file.
+ *
+ * @param name the name to get the source for
+ * @param binding the binding of the name
+ * @return the source string or null
, if the source could not be computed
+ * @throws CoreException if the file could not be loaded
+ */
+ private String computeSourceForName(IName name, IBinding binding) throws CoreException {
+ IASTFileLocation fileLocation= name.getFileLocation();
+ if (fileLocation == null) {
+ return null;
+ }
+ int nodeOffset= fileLocation.getNodeOffset();
+ int nodeLength= fileLocation.getNodeLength();
+
+ String fileName= fileLocation.getFileName();
+ //if (DEBUG) System.out.println("[CSourceHover] Computing source for " + name + " in " + fileName); //$NON-NLS-1$//$NON-NLS-2$
+ IPath location= Path.fromOSString(fileName);
+ LocationKind locationKind= LocationKind.LOCATION;
+ if (name instanceof IASTName && !name.isReference()) {
+ IASTName astName= (IASTName)name;
+ if (astName.getTranslationUnit().getFilePath().equals(fileName) && fTU.getResource() != null) {
+ // reuse editor buffer for names local to the translation unit
+ location= fTU.getResource().getFullPath();
+ locationKind= LocationKind.IFILE;
+ }
+ } else {
+ // try to resolve path to a resource for proper encoding (bug 221029)
+ IFile file= EditorUtility.getWorkspaceFileAtLocation(location, fTU);
+ if (file != null) {
+ location= file.getFullPath();
+ locationKind= LocationKind.IFILE;
+ if (name instanceof IIndexName) {
+ // need to adjust index offsets to current offsets
+ // in case file has been modified since last index time
+ IIndexName indexName= (IIndexName) name;
+ long timestamp= indexName.getFile().getTimestamp();
+ IPositionConverter converter= CCorePlugin.getPositionTrackerManager().findPositionConverter(file, timestamp);
+ if (converter != null) {
+ IRegion currentLocation= converter.historicToActual(new Region(nodeOffset, nodeLength));
+ nodeOffset= currentLocation.getOffset();
+ nodeLength= currentLocation.getLength();
+ }
+ }
+ }
+ }
+ ITextFileBufferManager mgr= FileBuffers.getTextFileBufferManager();
+ mgr.connect(location, locationKind, fMonitor);
+ ITextFileBuffer buffer= mgr.getTextFileBuffer(location, locationKind);
+ try {
+ IRegion nameRegion= new Region(nodeOffset, nodeLength);
+ final int nameOffset= nameRegion.getOffset();
+ final int sourceStart;
+ final int sourceEnd;
+ IDocument doc= buffer.getDocument();
+ if (nameOffset >= doc.getLength() || nodeLength <= 0) {
+ return null;
+ }
+ if (binding instanceof IMacroBinding) {
+ ITypedRegion partition= TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, nameOffset, false);
+ if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
+ int directiveStart= partition.getOffset();
+ int commentStart= searchCommentBackward(doc, directiveStart, -1);
+ if (commentStart >= 0) {
+ sourceStart= commentStart;
+ } else {
+ sourceStart= directiveStart;
+ }
+ sourceEnd= directiveStart + partition.getLength();
+ } else {
+ return null;
+ }
+ } else {
+ // expand source range to include preceding comment, if any
+ boolean isKnR= isKnRSource(name);
+ sourceStart= computeSourceStart(doc, nameOffset, binding, isKnR);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return null;
+ }
+ sourceEnd= computeSourceEnd(doc, nameOffset + nameRegion.getLength(), binding, name.isDefinition(), isKnR);
+ }
+ String source= buffer.getDocument().get(sourceStart, sourceEnd - sourceStart);
+ return source;
+
+ } catch (BadLocationException exc) {
+ // ignore - should not happen anyway
+ //if (DEBUG) exc.printStackTrace();
+ } finally {
+ mgr.disconnect(location, LocationKind.LOCATION, fMonitor);
+ }
+ return null;
+ }
+ /**
+ * Searches the start of the comment preceding the given source offset.
+ * Continuous line comments are considered as one comment until a block
+ * comment is reached or a non-comment partition.
+ *
+ * @param doc the document
+ * @param start the start of the backward search
+ * @param bound search boundary (exclusive)
+ * @return the comment start offset or -1
, if no suitable comment was found
+ * @throws BadLocationException
+ */
+ private static int searchCommentBackward(IDocument doc, int start, int bound) throws BadLocationException {
+ int firstLine= doc.getLineOfOffset(start);
+ if (firstLine == 0) {
+ return 0;
+ }
+ ITypedRegion partition= TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, start, true);
+ int currentOffset= Math.max(doc.getLineOffset(firstLine - 1), partition.getOffset() - 1);
+ int commentOffset= -1;
+ while (currentOffset > bound) {
+ partition= TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, currentOffset, true);
+ currentOffset= partition.getOffset() - 1;
+ if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())
+ || ICPartitions.C_MULTI_LINE_DOC_COMMENT.equals(partition.getType())) {
+ final int partitionOffset= partition.getOffset();
+ final int startLine= doc.getLineOfOffset(partitionOffset);
+ final int lineOffset= doc.getLineOffset(startLine);
+ if (partitionOffset == lineOffset ||
+ doc.get(lineOffset, partitionOffset - lineOffset).trim().length() == 0) {
+ return lineOffset;
+ }
+ return commentOffset;
+ } else if (ICPartitions.C_SINGLE_LINE_COMMENT.equals(partition.getType())
+ || ICPartitions.C_SINGLE_LINE_DOC_COMMENT.equals(partition.getType())) {
+ final int partitionOffset= partition.getOffset();
+ final int startLine= doc.getLineOfOffset(partitionOffset);
+ final int lineOffset= doc.getLineOffset(startLine);
+ if (partitionOffset == lineOffset ||
+ doc.get(lineOffset, partitionOffset - lineOffset).trim().length() == 0) {
+ commentOffset= lineOffset;
+ continue;
+ }
+ return commentOffset;
+ } else if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) {
+ if (doc.get(partition.getOffset(), partition.getLength()).trim().length() == 0) {
+ continue;
+ }
+ if (commentOffset >= 0) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ return commentOffset;
+ }
+ /**
+ * Determine if the name is part of a KnR function definition.
+ * @param name
+ * @return true
if the name is part of a KnR function
+ */
+ private boolean isKnRSource(IName name) {
+ if (name instanceof IASTName) {
+ IASTNode node= (IASTNode)name;
+ while (node.getParent() != null) {
+ if (node instanceof ICASTKnRFunctionDeclarator) {
+ return node.getParent() instanceof IASTFunctionDefinition;
+ }
+ node= node.getParent();
+ }
+ }
+ return false;
+ }
+ private int computeSourceStart(IDocument doc, int nameOffset, IBinding binding, boolean isKnR) throws BadLocationException {
+ int sourceStart= nameOffset;
+ CHeuristicScanner scanner= new CHeuristicScanner(doc);
+ if (binding instanceof IParameter) {
+ if (isKnR) {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { ')', ';' });
+ } else {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { '>', '(', ',' });
+ if (sourceStart > 0 && doc.getChar(sourceStart) == '>') {
+ sourceStart= scanner.findOpeningPeer(sourceStart - 1, '<', '>');
+ if (sourceStart > 0) {
+ sourceStart= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '(', ',' });
+ }
+ }
+ }
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return sourceStart;
+ }
+ sourceStart= scanner.findNonWhitespaceForward(sourceStart + 1, nameOffset);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ sourceStart = nameOffset;
+ }
+ } else if (binding instanceof ICPPTemplateParameter) {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { '>', '<', ',' });
+ if (sourceStart > 0 && doc.getChar(sourceStart) == '>') {
+ sourceStart= scanner.findOpeningPeer(sourceStart - 1, '<', '>');
+ if (sourceStart > 0) {
+ sourceStart= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '<', ',' });
+ }
+ }
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return sourceStart;
+ }
+ sourceStart= scanner.findNonWhitespaceForward(sourceStart + 1, nameOffset);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ sourceStart = nameOffset;
+ }
+ } else if (binding instanceof IEnumerator) {
+ sourceStart= scanner.scanBackward(nameOffset, CHeuristicScanner.UNBOUND, new char[] { '{', ',' });
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ return sourceStart;
+ }
+ sourceStart= scanner.findNonWhitespaceForward(sourceStart + 1, nameOffset);
+ if (sourceStart == CHeuristicScanner.NOT_FOUND) {
+ sourceStart = nameOffset;
+ }
+ } else {
+ final boolean expectClosingBrace;
+ IType type= null;
+ if (binding instanceof ITypedef) {
+ type= ((ITypedef)binding).getType();
+ } else if (binding instanceof IVariable) {
+ type= ((IVariable)binding).getType();
+ }
+ expectClosingBrace= type instanceof ICompositeType || type instanceof IEnumeration;
+ final int nameLine= doc.getLineOfOffset(nameOffset);
+ sourceStart= nameOffset;
+ int commentBound;
+ if (isKnR) {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { ')', ';' });
+ } else {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '{', '}', ';' });
+ }
+ while (expectClosingBrace && commentBound > 0 && doc.getChar(commentBound) == '}') {
+ int openingBrace= scanner.findOpeningPeer(commentBound - 1, '{', '}');
+ if (openingBrace != CHeuristicScanner.NOT_FOUND) {
+ sourceStart= openingBrace - 1;
+ }
+ if (isKnR) {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { ')', ';' });
+ } else {
+ commentBound= scanner.scanBackward(sourceStart, CHeuristicScanner.UNBOUND, new char[] { '{', '}', ';' });
+ }
+ }
+ if (commentBound == CHeuristicScanner.NOT_FOUND) {
+ commentBound= -1; // unbound
+ }
+ sourceStart= Math.min(sourceStart, doc.getLineOffset(nameLine));
+ int commentStart= searchCommentBackward(doc, sourceStart, commentBound);
+ if (commentStart >= 0) {
+ sourceStart= commentStart;
+ } else {
+ int nextNonWS= scanner.findNonWhitespaceForward(commentBound+1, sourceStart);
+ if (nextNonWS != CHeuristicScanner.NOT_FOUND) {
+ int nextNonWSLine= doc.getLineOfOffset(nextNonWS);
+ int lineOffset= doc.getLineOffset(nextNonWSLine);
+ if (doc.get(lineOffset, nextNonWS - lineOffset).trim().length() == 0) {
+ sourceStart= doc.getLineOffset(nextNonWSLine);
+ }
+ }
+ }
+ }
+ return sourceStart;
+ }
+ private int computeSourceEnd(IDocument doc, int start, IBinding binding, boolean isDefinition, boolean isKnR) throws BadLocationException {
+ int sourceEnd= start;
+ CHeuristicScanner scanner= new CHeuristicScanner(doc);
+ // expand forward to the end of the definition/declaration
+ boolean searchBrace= false;
+ boolean searchSemi= false;
+ boolean searchComma= false;
+ if (binding instanceof ICompositeType || binding instanceof IEnumeration) {
+ searchBrace= true;
+ } else if (binding instanceof ICPPTemplateDefinition) {
+ searchBrace= true;
+ } else if (binding instanceof IFunction && isDefinition) {
+ searchBrace= true;
+ } else if (binding instanceof IParameter) {
+ if (isKnR) {
+ searchSemi= true;
+ } else {
+ searchComma= true;
+ }
+ } else if (binding instanceof IEnumerator || binding instanceof ICPPTemplateParameter) {
+ searchComma= true;
+ } else if (binding instanceof IVariable || binding instanceof ITypedef) {
+ searchSemi= true;
+ } else if (!isDefinition) {
+ searchSemi= true;
+ }
+ if (searchBrace) {
+ int brace= scanner.scanForward(start, CHeuristicScanner.UNBOUND, '{');
+ if (brace != CHeuristicScanner.NOT_FOUND) {
+ sourceEnd= scanner.findClosingPeer(brace + 1, '{', '}');
+ if (sourceEnd == CHeuristicScanner.NOT_FOUND) {
+ sourceEnd= doc.getLength();
+ }
+ }
+ // expand region to include whole line
+ IRegion lineRegion= doc.getLineInformationOfOffset(sourceEnd);
+ sourceEnd= lineRegion.getOffset() + lineRegion.getLength();
+ } else if (searchSemi) {
+ int semi= scanner.scanForward(start, CHeuristicScanner.UNBOUND, ';');
+ if (semi != CHeuristicScanner.NOT_FOUND) {
+ sourceEnd= semi+1;
+ }
+ // expand region to include whole line
+ IRegion lineRegion= doc.getLineInformationOfOffset(sourceEnd);
+ sourceEnd= lineRegion.getOffset() + lineRegion.getLength();
+ } else if (searchComma) {
+ int bound;
+ if (binding instanceof IParameter) {
+ bound= scanner.findClosingPeer(start, '(', ')');
+ } else if (binding instanceof ICPPTemplateParameter) {
+ bound= scanner.findClosingPeer(start, '<', '>');
+ } else if (binding instanceof IEnumerator) {
+ bound= scanner.findClosingPeer(start, '{', '}');
+ } else {
+ bound = CHeuristicScanner.NOT_FOUND;
+ }
+ if (bound == CHeuristicScanner.NOT_FOUND) {
+ bound= Math.min(doc.getLength(), start + 100);
+ }
+ int comma= scanner.scanForward(start, bound, ',');
+ if (comma == CHeuristicScanner.NOT_FOUND) {
+ // last argument
+ sourceEnd= bound;
+ } else {
+ sourceEnd= comma;
+ // expand region to include whole line if rest is comment
+ IRegion lineRegion= doc.getLineInformationOfOffset(sourceEnd);
+ int lineEnd= lineRegion.getOffset() + lineRegion.getLength();
+ int nextNonWS= scanner.findNonWhitespaceForwardInAnyPartition(sourceEnd + 1, lineEnd);
+ if (nextNonWS != CHeuristicScanner.NOT_FOUND) {
+ String contentType= TextUtilities.getContentType(doc, ICPartitions.C_PARTITIONING, nextNonWS, false);
+ if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType) || ICPartitions.C_SINGLE_LINE_COMMENT.equals(contentType)) {
+ sourceEnd= lineEnd;
+ }
+ }
+ }
+ }
+ return sourceEnd;
+ }
+
+ /**
* Test whether the invocation offset is inside or before the preprocessor directive keyword.
*
* @param context the invocation context
diff --git a/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPreferenceInitializer.java b/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPreferenceInitializer.java
index 60d6458..deb2213 100644
--- a/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPreferenceInitializer.java
+++ b/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPreferenceInitializer.java
@@ -10,6 +10,14 @@
*******************************************************************************/
package org.eclipse.cdt.ui;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
import org.eclipse.cdt.internal.ui.cview.CView;
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightings;
import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage;
@@ -18,6 +26,7 @@ import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage;
import org.eclipse.cdt.internal.ui.preferences.CodeAssistPreferencePage;
import org.eclipse.cdt.internal.ui.preferences.WorkInProgressPreferencePage;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.editors.text.EditorsUI;
@@ -30,7 +39,13 @@ import org.eclipse.ui.texteditor.AbstractTextEditor;
* @noextend This class is not intended to be subclassed by clients.
*/
public class CUIPreferenceInitializer extends AbstractPreferenceInitializer {
-
+
+ private static boolean isFirst = true;
+ private static final String path = "plugins";
+ private static final String fileName = "org.tizen.cpp.apireference";
+ public static String doxygenJarFilePath;
+ public static String doxygenDirectoryPath;
+
/* (non-Javadoc)
* @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
*/
@@ -38,7 +53,7 @@ public class CUIPreferenceInitializer extends AbstractPreferenceInitializer {
public void initializeDefaultPreferences() {
final IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore();
- PreferenceConstants.initializeDefaultValues(store);
+ PreferenceConstants.initializeDefaultValues(store);
CPluginPreferencePage.initDefaults(store);
BuildConsolePreferencePage.initDefaults(store);
CView.initDefaults(store);
@@ -52,14 +67,86 @@ public class CUIPreferenceInitializer extends AbstractPreferenceInitializer {
// All of those settings are now in the workbench "All TextEditor" preference Page.
// Later we should remove this calls, after CDT-3.0
EditorsUI.useAnnotationsPreferencePage(store);
- EditorsUI.useQuickDiffPreferencePage(store);
+ EditorsUI.useQuickDiffPreferencePage(store);
useTextEditorPreferencePage(store);
+
+ if (isFirst == true) {
+ setPath();
+ extractJarFile();
+ }
+ }
+
+ /**
+ * Set doxygenJarFilePath and doxygenDirectoryPath.
+ */
+ private void setPath() {
+ isFirst = false;
+ String eclipseRootPath = Platform.getInstallLocation().getURL().getPath();
+ // In Windows, path is like /D:/works/workspace/slp/indigo-winpde/eclipse/
+ if (System.getProperty("os.name").startsWith("Windows"))
+ eclipseRootPath = eclipseRootPath.substring(1, eclipseRootPath.length());
+
+ String eclipsePluginPath = eclipseRootPath + path;
+ String doxygenJarFileName = null;
+ File file = new File(eclipsePluginPath);
+ File fileList[] = file.listFiles();
+ for (int i = 0; i < fileList.length; i++) {
+ if (fileList[i].getName().contains(fileName)) {
+ doxygenJarFileName = fileList[i].getName();
+ }
+ }
+
+ doxygenJarFilePath = eclipseRootPath + path + "/" + doxygenJarFileName;
+ doxygenDirectoryPath = eclipseRootPath + path + "/" + fileName;
+ }
+
+ /**
+ * Extract jar file.
+ */
+ private void extractJarFile() {
+ try {
+ JarFile jarFile = new JarFile(doxygenJarFilePath);
+ File destinationDir = new File(doxygenDirectoryPath);
+ if (!destinationDir.exists()) {
+ destinationDir.mkdirs();
+ } else if (destinationDir.exists()) {
+ return;
+ }
+ for (EnumerationAbout This Content
+
+License
+
+
+ *
+ *
+ * createArrayTypeBindingKey("LObject;", 1) -> "[LObject;"
+ *
+ *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param typeKey the binding key of the given type + * @param arrayDimension the given array dimension + * @return a new array type binding key + */ + public static String createArrayTypeBindingKey(String typeKey, int arrayDimension) { + // Note this implementation is heavily dependent on ArrayTypeBinding#computeUniqueKey() + StringBuffer buffer = new StringBuffer(); + while (arrayDimension-- > 0) + buffer.append('['); + buffer.append(typeKey); + return buffer.toString(); + } + + /** + * Creates a new type binding key from the given type name. + *+ * For example: + *
+ *
+ * createTypeBindingKey("String") -> "LString;"
+ *
+ *
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param typeName the possibly qualified type name + * @return a new type binding key + */ + public static String createTypeBindingKey(String typeName) { + // Note this implementation is heavily dependent on TypeBinding#computeUniqueKey() and its subclasses + return Signature.createTypeSignature(typeName.replace('.', '/'), true/*resolved*/); + } + + /** + * Transforms this binding key into a resolved signature. + * If this binding key represents a field, the returned signature is + * the declaring type's signature. + * + * @return the resolved signature for this binding key + * @see Signature + */ + public String toSignature() { + KeyToSignature keyToSignature = new KeyToSignature(this.key, KeyToSignature.SIGNATURE); + keyToSignature.parse(); + return keyToSignature.signature.toString(); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return this.key; + } +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/BufferChangedEvent.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/BufferChangedEvent.java new file mode 100644 index 0000000..207ba45 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/BufferChangedEvent.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import java.util.EventObject; + +/** + * A buffer changed event describes how a buffer has changed. These events are + * used inIBufferChangedListener
notifications.
+ *
+ * For text insertions, getOffset
is the offset
+ * of the first inserted character, getText
is the
+ * inserted text, and getLength
is 0.
+ *
+ * For text removals, getOffset
is the offset
+ * of the first removed character, getText
is null
,
+ * and getLength
is the length of the text that was removed.
+ *
+ * For replacements (including IBuffer.setContents
),
+ * getOffset
is the offset
+ * of the first replaced character, getText
is the replacement
+ * text, and getLength
is the length of the original text
+ * that was replaced.
+ *
+ * When a buffer is closed, getOffset
is 0, getLength
+ * is 0, and getText
is null
.
+ *
+ * This class is not intended to be instantiated or subclassed by clients. + * Instances of this class are automatically created by the JavaScript model. + *
+ * + * @see IBuffer + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class BufferChangedEvent extends EventObject { + + /** + * The length of text that has been modified in the buffer. + */ + private int length; + + /** + * The offset into the buffer where the modification took place. + */ + private int offset; + + /** + * The text that was modified. + */ + private String text; + + private static final long serialVersionUID = 655379473891745999L; // backward compatible + +/** + * Creates a new buffer changed event indicating that the given buffer has changed. + * + * @param buffer the given buffer + * @param offset the given offset + * @param length the given length + * @param text the given text + */ +public BufferChangedEvent(IBuffer buffer, int offset, int length, String text) { + super(buffer); + this.offset = offset; + this.length = length; + this.text = text; +} +/** + * Returns the buffer which has changed. + * + * @return the buffer affected by the change + */ +public IBuffer getBuffer() { + return (IBuffer) this.source; +} +/** + * Returns the length of text removed or replaced in the buffer, or + * 0 if text has been inserted into the buffer. + * + * @return the length of the original text fragment modified by the + * buffer change ( 0
in case of insertion).
+ */
+public int getLength() {
+ return this.length;
+}
+/**
+ * Returns the index of the first character inserted, removed, or replaced
+ * in the buffer.
+ *
+ * @return the source offset of the textual manipulation in the buffer
+ */
+public int getOffset() {
+ return this.offset;
+}
+/**
+ * Returns the text that was inserted, the replacement text,
+ * or null
if text has been removed.
+ *
+ * @return the text corresponding to the buffer change ( null
+ * in case of deletion).
+ */
+public String getText() {
+ return this.text;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionContext.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionContext.java
new file mode 100644
index 0000000..4bda771
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionContext.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.wst.jsdt.internal.codeassist.InternalCompletionContext;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadoc;
+
+/**
+ * Completion context.
+ *
+ * Represent the context in which the completion occurs.
+ * + * This class is not intended to be instantiated or subclassed by clients. + *
+ * + * @see CompletionRequestor#acceptContext(CompletionContext) + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class CompletionContext extends InternalCompletionContext { + + /** + * The completion token is unknown. + */ + public static final int TOKEN_KIND_UNKNOWN = 0; + + /** + * The completion token is a name. + */ + public static final int TOKEN_KIND_NAME = 1; + /** + * The completion token is a string literal. + * The string literal ends quote can be not present the source. + *"foo"
or "foo
.
+ */
+ public static final int TOKEN_KIND_STRING_LITERAL = 2;
+
+ /**
+ * Tell user whether completion takes place in a jsdoc comment or not.
+ *
+ * @return boolean true if completion takes place in a jsdoc comment, false otherwise.
+ */
+ public boolean isInJsdoc() {
+ return this.javadoc != 0;
+ }
+
+ /**
+ * Tell user whether completion takes place in text area of a jsdoc comment or not.
+ *
+ * @return boolean true if completion takes place in a text area of a jsdoc comment, false otherwise.
+ */
+ public boolean isInJsdocText() {
+ return (this.javadoc & CompletionOnJavadoc.TEXT) != 0;
+ }
+
+ /**
+ * Tell user whether completion takes place in a formal reference of a jsdoc tag or not.
+ * Tags with formal reference are:
+ * null
if there is no expected types.
+ *
+ * @see Signature
+ */
+ public char[][] getExpectedTypesSignatures() {
+ return this.expectedTypesSignatures;
+ }
+ /**
+ * Return keys of expected types of a potential completion proposal at the completion position.
+ *
+ * It's not mandatory to a completion proposal to respect this expectation.
+ *
+ * @return keys of expected types of a potential completion proposal at the completion position or
+ * null
if there is no expected types.
+ *
+ * @see org.eclipse.wst.jsdt.core.dom.ASTParser#createASTs(IJavaScriptUnit[], String[], org.eclipse.wst.jsdt.core.dom.ASTRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public char[][] getExpectedTypesKeys() {
+ return this.expectedTypesKeys;
+ }
+
+ /**
+ * Returns the completed token.
+ * This token is either the identifier or JavaScript language keyword
+ * or the string literal under, immediately preceding,
+ * the original request offset. If the original request offset
+ * is not within or immediately after an identifier or keyword or
+ * a string literal then the returned value is null
.
+ *
+ * @return completed token or null
+ */
+ public char[] getToken() {
+ return this.token;
+ }
+
+ /**
+ * Returns the kind of completion token being proposed.
+ * + * The set of different kinds of completion token is + * expected to change over time. It is strongly recommended + * that clients do not assume that the kind is one of the + * ones they know about, and code defensively for the + * possibility of unexpected future growth. + *
+ * + * @return the kind; one of the kind constants declared on + * this class whose name starts withTOKEN_KIND
,
+ * or possibly a kind unknown to the caller
+ */
+ public int getTokenKind() {
+ return this.tokenKind;
+ }
+
+ /**
+ * Returns the character index of the start of the
+ * subrange in the source file buffer containing the
+ * relevant token being completed. This
+ * token is either the identifier or JavaScript language keyword
+ * under, or immediately preceding, the original request
+ * offset. If the original request offset is not within
+ * or immediately after an identifier or keyword, then the
+ * position returned is original request offset and the
+ * token range is empty.
+ *
+ * @return character index of token start position (inclusive)
+ */
+ public int getTokenStart() {
+ return this.tokenStart;
+ }
+
+ /**
+ * Returns the character index of the end (exclusive) of the subrange
+ * in the source file buffer containing the
+ * relevant token. When there is no relevant token, the
+ * range is empty
+ * (getTokenEnd() == getTokenStart() - 1
).
+ *
+ * @return character index of token end position (exclusive)
+ */
+ public int getTokenEnd() {
+ return this.tokenEnd;
+ }
+
+ /**
+ * Returns the offset position in the source file buffer
+ * after which code assist is requested.
+ *
+ * @return offset position in the source file buffer
+ */
+ public int getOffset() {
+ return this.offset;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("completion offset="); //$NON-NLS-1$
+ buffer.append(this.offset);
+ buffer.append('\n');
+
+ buffer.append("completion range=["); //$NON-NLS-1$
+ buffer.append(this.tokenStart);
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append(this.tokenEnd);
+ buffer.append("]\n"); //$NON-NLS-1$
+
+ buffer.append("completion token="); //$NON-NLS-1$
+ String string = "null"; //$NON-NLS-1$
+ if(token == null) {
+ buffer.append(string);
+ } else {
+ buffer.append('\"');
+ buffer.append(this.token);
+ buffer.append('\"');
+ }
+ buffer.append('\n');
+
+ buffer.append("expectedTypesSignatures="); //$NON-NLS-1$
+ if(this.expectedTypesSignatures == null) {
+ buffer.append(string);
+ } else {
+ buffer.append('{');
+ for (int i = 0; i < this.expectedTypesSignatures.length; i++) {
+ if(i > 0) buffer.append(',');
+ buffer.append(this.expectedTypesSignatures[i]);
+
+ }
+ buffer.append('}');
+ }
+ buffer.append('\n');
+
+ buffer.append("expectedTypesKeys="); //$NON-NLS-1$
+ if(expectedTypesSignatures == null) {
+ buffer.append(string);
+ } else {
+ buffer.append('{');
+ for (int i = 0; i < this.expectedTypesKeys.length; i++) {
+ if(i > 0) buffer.append(',');
+ buffer.append(this.expectedTypesKeys[i]);
+
+ }
+ buffer.append('}');
+ }
+ buffer.append('\n');
+
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionFlags.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionFlags.java
new file mode 100644
index 0000000..eda1d9e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionFlags.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * Utility class for decoding additional flags in completion proposal.
+ * + * This class provides static methods only; it is not intended to be + * instantiated or subclassed by clients. + *
+ * + * @see CompletionProposal#getAdditionalFlags() + * + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class CompletionFlags { + /** + * Constant representing the absence of any flag + */ + public static final int Default = 0x0000; + + /** + * Not instantiable. + */ + private CompletionFlags() { + // Not instantiable + } +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java new file mode 100644 index 0000000..2016b89 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CompletionProposal.java @@ -0,0 +1,2041 @@ +/******************************************************************************* + * Copyright (c) 2004, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.wst.jsdt.core.compiler.CharOperation; +import org.eclipse.wst.jsdt.internal.codeassist.InternalCompletionProposal; + +/** + * Completion proposal. + *
+ * In typical usage, the user working in a JavaScript code editor issues
+ * a code assist command. This command results in a call to
+ * ICodeAssist.codeComplete(position, completionRequestor)
+ * passing the current position in the source code. The code assist
+ * engine analyzes the code in the buffer, determines what kind of
+ * JavaScript language construct is at that position, and proposes ways
+ * to complete that construct. These proposals are instances of
+ * the class CompletionProposal
. These proposals,
+ * perhaps after sorting and filtering, are presented to the user
+ * to make a choice.
+ *
+ * The proposal is as follows: insert
+ * the {@linkplain #getCompletion() completion string} into the
+ * source file buffer, replacing the characters between
+ * {@linkplain #getReplaceStart() the start}
+ * and {@linkplain #getReplaceEnd() end}. The string
+ * can be arbitrary; for example, it might include not only the
+ * name of a function but a set of parentheses. Moreover, the source
+ * range may include source positions before or after the source
+ * position where ICodeAssist.codeComplete
was invoked.
+ * The rest of the information associated with the proposal is
+ * to provide context that may help a user to choose from among
+ * competing proposals.
+ *
+ * The completion engine creates instances of this class; it is not intended + * to be instantiated or subclassed by clients. + *
+ * + * @see ICodeAssist#codeComplete(int, CompletionRequestor) + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class CompletionProposal extends InternalCompletionProposal { + private boolean updateCompletion = false; + + /** + * Completion is a declaration of an anonymous class. + * This kind of completion might occur in a context like + *"new List^;"
and complete it to
+ * "new List() {}"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"this.ref^ = 0;"
and complete it to
+ * "this.refcount = 0;"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"fu Foo {}"
and complete it to
+ * "function Foo {}"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"break lo^;"
and complete it to
+ * "break loop;"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"ke^ = 4;"
and complete it to
+ * "keys = 4;"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"myObject.pr^();"
and complete it to
+ * ""myObject.println();"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"import java.u^.*;"
and complete it to
+ * "import java.util.*;"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"var c=new Str^ ;"
and complete it to
+ * "var c=new String ;"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
" * blabla System.o^ blabla"
and complete it to
+ * " * blabla {@link System#out } blabla"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
" * blabla Object#va^ blabla"
and complete it to
+ * " * blabla {@link Object#valueOf() }"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
" * blabla Str^ blabla"
and complete it to
+ * " * blabla {@link String } blabla"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
" * @s^ blabla"
and complete it to
+ * " * @see blabla"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
" * Insert @l^ Object"
and complete it to
+ * " * Insert {@link Object }"
.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
"new Lis"
and complete it to
+ * "new List();"
if List is a class that is not abstract.
+ * + * The following additional context information is available + * for this kind of completion proposal at little extra cost: + *
+ * This kind of proposal could require a long computation, so they are computed only if completion operation is called with a {@link IProgressMonitor}
+ * (e.g. {@link ICodeAssist#codeComplete(int, CompletionRequestor, IProgressMonitor)}).
+ * This kind of proposal is always is only proposals with a {@link #TYPE_REF} required proposal, so this kind of required proposal must be allowed:
+ * requestor.setAllowsRequiredProposals(CONSTRUCTOR_INVOCATION, TYPE_REF, true)
.
+ *
null
if none.
+ * Defaults to null.
+ */
+ private char[] declarationSignature = null;
+
+ /**
+ * Unique key of the relevant package or type declaration
+ * in the context, or null
if none.
+ * Defaults to null.
+ */
+ private char[] declarationKey = null;
+
+ /**
+ * Simple name of the method, field,
+ * member, or variable relevant in the context, or
+ * null
if none.
+ * Defaults to null.
+ */
+ private char[] name = null;
+
+ /**
+ * Signature of the function, field type, member type,
+ * relevant in the context, or null
if none.
+ * Defaults to null.
+ */
+ private char[] signature = null;
+
+ /**
+ * Unique of the function, field type, member type,
+ * relevant in the context, or null
if none.
+ * Defaults to null.
+ */
+ private char[] key = null;
+
+ /**
+ * Array of required completion proposals, or null
if none.
+ * The proposal can not be applied if the required proposals aren't applied.
+ * Defaults to null
.
+ */
+ private CompletionProposal[] requiredProposals;
+
+ /**
+ * Modifier flags relevant in the context, or
+ * Flags.AccDefault
if none.
+ * Defaults to Flags.AccDefault
.
+ */
+ private int flags = Flags.AccDefault;
+
+ /**
+ * Completion flags relevant in the context, or
+ * CompletionFlags.Default
if none.
+ * Defaults to CompletionFlags.Default
.
+ */
+ private int additionalFlags = CompletionFlags.Default;
+
+ /**
+ * Parameter names (for method completions), or
+ * null
if none. Lazily computed.
+ * Defaults to null
.
+ */
+ private char[][] parameterNames = null;
+
+ /**
+ * Indicates whether parameter names have been computed.
+ */
+ private boolean parameterNamesComputed = false;
+
+ /**
+ * Indicates the start offset of local variable declaration
+ */
+ private int sourceStart = -1;
+ /**
+ * Indicates the end offset of local variable declaration
+ */
+ private int sourceEnd = -1;
+
+ /**
+ * Creates a basic completion proposal. All instance
+ * field have plausible default values unless otherwise noted.
+ * + * Note that the constructors for this class are internal to the + * JavaScript model implementation. Clients cannot directly create + * CompletionProposal objects. + *
+ * + * @param kind one of the kind constants declared on this class + * @param completionOffset original offset of code completion request + * @return a new completion proposal + */ + public static CompletionProposal create(int kind, int completionOffset) { + return new CompletionProposal(kind, completionOffset); + } + + /** + * Creates a basic completion proposal. All instance + * field have plausible default values unless otherwise noted. + *+ * Note that the constructors for this class are internal to the + * JavaScript model implementation. Clients cannot directly create + * CompletionProposal objects. + *
+ * + * @param kind one of the kind constants declared on this class + * @param completionLocation original offset of code completion request + */ + CompletionProposal(int kind, int completionLocation) { + if ((kind < CompletionProposal.FIRST_KIND) + || (kind > CompletionProposal.LAST_KIND)) { + throw new IllegalArgumentException(); + } + if (this.completion == null || completionLocation < 0) { + // Work around for bug 132558 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=132558). + // completionLocation can be -1 if the completion occur at the start of a file or + // the start of a code snippet but this API isn't design to support negative position. + if(this.completion == null || completionLocation != -1) { + throw new IllegalArgumentException(); + } + completionLocation = 0; + } + this.completionKind = kind; + this.completionLocation = completionLocation; + } + + /** + * Returns the completion flags relevant in the context, or + *CompletionFlags.Default
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
FIELD_IMPORT
- completion flags
+ * of the attribute that is referenced. Completion flags for
+ * this proposal kind can only include CompletionFlags.StaticImport
METHOD_IMPORT
- completion flags
+ * of the attribute that is referenced. Completion flags for
+ * this proposal kind can only include CompletionFlags.StaticImport
TYPE_IMPORT
- completion flags
+ * of the attribute that is referenced. Completion flags for
+ * this proposal kind can only include CompletionFlags.StaticImport
CompletionFlags.Default
.
+ *
+ *
+ * @return the completion flags, or
+ * CompletionFlags.Default
if none
+ * @see CompletionFlags
+ *
+ */
+ public int getAdditionalFlags() {
+ return this.additionalFlags;
+ }
+
+ /**
+ * Sets the completion flags relevant in the context.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param additionalFlags the completion flags, or + *CompletionFlags.Default
if none
+ *
+ */
+ public void setAdditionalFlags(int additionalFlags) {
+ this.additionalFlags = additionalFlags;
+ }
+
+ /**
+ * Returns the kind of completion being proposed.
+ * + * The set of different kinds of completion proposals is + * expected to change over time. It is strongly recommended + * that clients do not assume that the kind is one of the + * ones they know about, and code defensively for the + * possibility of unexpected future growth. + *
+ * + * @return the kind; one of the kind constants + * declared on this class, or possibly a kind unknown + * to the caller + */ + public int getKind() { + return this.completionKind; + } + + /** + * Returns the character index in the source file buffer + * where source completion was requested (the + *offset
parameter to
+ * ICodeAssist.codeComplete
minus one).
+ *
+ * @return character index in source file buffer
+ * @see ICodeAssist#codeComplete(int,CompletionRequestor)
+ */
+ // TODO (david) https://bugs.eclipse.org/bugs/show_bug.cgi?id=132558
+ public int getCompletionLocation() {
+ return this.completionLocation;
+ }
+
+ /**
+ * Returns the character index of the start of the
+ * subrange in the source file buffer containing the
+ * relevant token being completed. This
+ * token is either the identifier or JavaScript language keyword
+ * under, or immediately preceding, the original request
+ * offset. If the original request offset is not within
+ * or immediately after an identifier or keyword, then the
+ * position returned is original request offset and the
+ * token range is empty.
+ *
+ * @return character index of token start position (inclusive)
+ */
+ public int getTokenStart() {
+ return this.tokenStart;
+ }
+
+ /**
+ * Returns the character index of the end (exclusive) of the subrange
+ * in the source file buffer containing the
+ * relevant token. When there is no relevant token, the
+ * range is empty
+ * (getEndToken() == getStartToken()
).
+ *
+ * @return character index of token end position (exclusive)
+ */
+ public int getTokenEnd() {
+ return this.tokenEnd;
+ }
+
+ /**
+ * Sets the character indices of the subrange in the
+ * source file buffer containing the relevant token being
+ * completed. This token is either the identifier or
+ * JavaScript language keyword under, or immediately preceding,
+ * the original request offset. If the original request
+ * offset is not within or immediately after an identifier
+ * or keyword, then the source range begins at original
+ * request offset and is empty.
+ * + * If not set, defaults to empty subrange at [0,0). + *
+ * + * @param startIndex character index of token start position (inclusive) + * @param endIndex character index of token end position (exclusive) + */ + public void setTokenRange(int startIndex, int endIndex) { + if (startIndex < 0 || endIndex < startIndex) { + throw new IllegalArgumentException(); + } + this.tokenStart = startIndex; + this.tokenEnd = endIndex; + } + + /** + * Returns the proposed sequence of characters to insert into the + * source file buffer, replacing the characters at the specified + * source range. The string can be arbitrary; for example, it might + * include not only the name of a method but a set of parentheses. + *+ * The client must not modify the array returned. + *
+ * + * @return the completion string + */ + public char[] getCompletion() { + if(this.completionKind == METHOD_DECLARATION) { + this.findParameterNames(null); + if(this.updateCompletion) { + this.updateCompletion = false; + + if(this.parameterNames != null) { + int length = this.parameterNames.length; + StringBuffer completionBuffer = new StringBuffer(this.completion.length); + + int start = 0; + int end = CharOperation.indexOf('%', this.completion); + + completionBuffer.append(this.completion, start, end - start); + + for(int i = 0 ; i < length ; i++){ + completionBuffer.append(this.parameterNames[i]); + start = end + 1; + end = CharOperation.indexOf('%', this.completion, start); + if(end > -1){ + completionBuffer.append(this.completion, start, end - start); + } else { + completionBuffer.append(this.completion, start, this.completion.length - start); + } + } + int nameLength = completionBuffer.length(); + this.completion = new char[nameLength]; + completionBuffer.getChars(0, nameLength, this.completion, 0); + } + } + } + return this.completion; + } + + /** + * Sets the proposed sequence of characters to insert into the + * source file buffer, replacing the characters at the specified + * source range. The string can be arbitrary; for example, it might + * include not only the name of a method but a set of parentheses. + *+ * If not set, defaults to an empty character array. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param completion the completion string + */ + public void setCompletion(char[] completion) { + this.completion = completion; + } + + /** + * Returns the character index of the start of the + * subrange in the source file buffer to be replaced + * by the completion string. If the subrange is empty + * (getReplaceEnd() == getReplaceStart()
),
+ * the completion string is to be inserted at this
+ * index.
+ * + * Note that while the token subrange is precisely + * specified, the replacement range is loosely + * constrained and may not bear any direct relation + * to the original request offset. For example, + * it would be possible for a type completion to + * propose inserting an import declaration at the + * top of the compilation unit; or the completion + * might include trailing parentheses and + * punctuation for a method completion. + *
+ * + * @return replacement start position (inclusive) + */ + public int getReplaceStart() { + return this.replaceStart; + } + + /** + * Returns the character index of the end of the + * subrange in the source file buffer to be replaced + * by the completion string. If the subrange is empty + * (getReplaceEnd() == getReplaceStart()
),
+ * the completion string is to be inserted at this
+ * index.
+ *
+ * @return replacement end position (exclusive)
+ */
+ public int getReplaceEnd() {
+ return this.replaceEnd;
+ }
+
+ /**
+ * Sets the character indices of the subrange in the
+ * source file buffer to be replaced by the completion
+ * string. If the subrange is empty
+ * (startIndex == endIndex
),
+ * the completion string is to be inserted at this
+ * index.
+ * + * If not set, defaults to empty subrange at [0,0). + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param startIndex character index of replacement start position (inclusive) + * @param endIndex character index of replacement end position (exclusive) + */ + public void setReplaceRange(int startIndex, int endIndex) { + if (startIndex < 0 || endIndex < startIndex) { + throw new IllegalArgumentException(); + } + this.replaceStart = startIndex; + this.replaceEnd = endIndex; + } + + /** + * Returns the relative relevance rating of this proposal. + * + * @return relevance rating of this proposal; ratings are positive; higher means better + */ + public int getRelevance() { + return this.relevance; + } + + /** + * Sets the relative relevance rating of this proposal. + *+ * If not set, defaults to the lowest possible rating (1). + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param rating relevance rating of this proposal; ratings are positive; higher means better + */ + public void setRelevance(int rating) { + if (rating <= 0) { + throw new IllegalArgumentException(); + } + this.relevance = rating; + } + + /** + * Returns the type signature of the relevant + * declaration in the context, ornull
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
ANNOTATION_ATTRIBUT_REF
- type signature
+ * of the annotation that declares the attribute that is referencedANONYMOUS_CLASS_DECLARATION
- type signature
+ * of the type that is being subclassed or implementedFIELD_IMPORT
- type signature
+ * of the type that declares the field that is importedFIELD_REF
- type signature
+ * of the type that declares the field that is referencedMETHOD_IMPORT
- type signature
+ * of the type that declares the method that is importedFUNCTION_REF
- type signature
+ * of the type that declares the method that is referencedFUNCTION_DECLARATION
- type signature
+ * of the type that declares the method that is being
+ * implemented or overriddenPACKAGE_REF
- dot-based package
+ * name of the package that is referencedTYPE_IMPORT
- dot-based package
+ * name of the package containing the type that is importedTYPE_REF
- dot-based package
+ * name of the package containing the type that is referencedPOTENTIAL_METHOD_DECLARATION
- type signature
+ * of the type that declares the method that is being creatednull
. Clients must not modify the array
+ * returned.
+ *
+ *
+ * @return a type signature or a package name (depending
+ * on the kind of completion), or null
if none
+ * @see Signature
+ */
+ public char[] getDeclarationSignature() {
+ return this.declarationSignature;
+ }
+
+ /**
+ * Returns the key of the relevant
+ * declaration in the context, or null
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
ANONYMOUS_CLASS_DECLARATION
- key
+ * of the type that is being subclassed or implementedFUNCTION_DECLARATION
- key
+ * of the type that declares the method that is being
+ * implemented or overriddennull
. Clients must not modify the array
+ * returned.
+ *
+ *
+ * @return a key, or null
if none
+ * @see org.eclipse.wst.jsdt.core.dom.ASTParser#createASTs(IJavaScriptUnit[], String[], org.eclipse.wst.jsdt.core.dom.ASTRequestor, IProgressMonitor)
+ */
+ public char[] getDeclarationKey() {
+ return this.declarationKey;
+ }
+
+ /**
+ * Sets the type signature of the relevant
+ * declaration in the context, or null
if none.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param signature the type or package signature, or + *null
if none
+ */
+ public void setDeclarationSignature(char[] signature) {
+ this.declarationSignature = signature;
+ }
+
+ /**
+ * Sets the type key of the relevant
+ * declaration in the context, or null
if none.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param key the type or package key, or + *null
if none
+ */
+ public void setDeclarationKey(char[] key) {
+ this.declarationKey = key;
+ }
+
+ /**
+ * Returns the simple name of the function, field,
+ * member, or variable relevant in the context, or
+ * null
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
ANNOTATION_ATTRIBUT_REF
- the name of the attributeFIELD_IMPORT
- the name of the fieldFIELD_REF
- the name of the fieldKEYWORD
- the keywordLABEL_REF
- the name of the labelLOCAL_VARIABLE_REF
- the name of the local variableMETHOD_IMPORT
- the name of the methodFUNCTION_REF
- the name of the method (the type simple name for constructor)FUNCTION_DECLARATION
- the name of the method (the type simple name for constructor)VARIABLE_DECLARATION
- the name of the variablePOTENTIAL_METHOD_DECLARATION
- the name of the methodnull
. Clients must not modify the array
+ * returned.
+ *
+ *
+ * @return the keyword, field, method, local variable, or member
+ * name, or null
if none
+ */
+ public char[] getName() {
+ return this.name;
+ }
+
+
+ /**
+ * Sets the simple name of the method (type simple name for constructor), field,
+ * member, or variable relevant in the context, or
+ * null
if none.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param name the keyword, field, method, local variable, + * or member name, ornull
if none
+ */
+ public void setName(char[] name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the signature of the method or type
+ * relevant in the context, or null
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
ANNOTATION_ATTRIBUT_REF
- the type signature
+ * of the referenced attribute's typeANONYMOUS_CLASS_DECLARATION
- method signature
+ * of the constructor that is being invokedFIELD_IMPORT
- the type signature
+ * of the referenced field's typeFIELD_REF
- the type signature
+ * of the referenced field's typeLOCAL_VARIABLE_REF
- the type signature
+ * of the referenced local variable's typeMETHOD_IMPORT
- method signature
+ * of the method that is importedFUNCTION_REF
- method signature
+ * of the method that is referencedFUNCTION_DECLARATION
- method signature
+ * of the method that is being implemented or overriddenTYPE_IMPORT
- type signature
+ * of the type that is importedTYPE_REF
- type signature
+ * of the type that is referencedVARIABLE_DECLARATION
- the type signature
+ * of the type of the variable being declaredPOTENTIAL_METHOD_DECLARATION
- method signature
+ * of the method that is being creatednull
. Clients must not modify the array
+ * returned.
+ *
+ *
+ * @return the signature, or null
if none
+ * @see Signature
+ */
+ public char[] getSignature() {
+ return this.signature;
+ }
+
+ /**
+ * Returns the key relevant in the context,
+ * or null
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
ANONYMOUS_CLASS_DECLARATION
- method key
+ * of the constructor that is being invoked, or null
if
+ * the declaring type is an interfaceFUNCTION_DECLARATION
- method key
+ * of the method that is being implemented or overriddennull
. Clients must not modify the array
+ * returned.
+ *
+ *
+ * @return the key, or null
if none
+ * @see org.eclipse.wst.jsdt.core.dom.ASTParser#createASTs(IJavaScriptUnit[], String[], org.eclipse.wst.jsdt.core.dom.ASTRequestor, IProgressMonitor)
+ */
+ public char[] getKey() {
+ return this.key;
+ }
+
+// /**
+// * Returns the package name of the relevant
+// * declaration in the context, or null
if none.
+// * +// * This field is available for the following kinds of +// * completion proposals: +// *
ANONYMOUS_CLASS_DECLARATION
- the dot-based package name
+// * of the type that is being subclassed or implementedFIELD_REF
- the dot-based package name
+// * of the type that declares the field that is referencedFUNCTION_REF
- the dot-based package name
+// * of the type that declares the method that is referencedFUNCTION_DECLARATION
- the dot-based package name
+// * of the type that declares the method that is being
+// * implemented or overriddennull
. Clients must not modify the array
+// * returned.
+// *
+// *
+// * @return the dot-based package name, or
+// * null
if none
+// * @see #getDeclarationSignature()
+// * @see #getSignature()
+// *
+// */
+// public char[] getDeclarationPackageName() {
+// return this.declarationPackageName;
+// }
+//
+// /**
+// * Returns the type name of the relevant
+// * declaration in the context without the package fragment,
+// * or null
if none.
+// * +// * This field is available for the following kinds of +// * completion proposals: +// *
ANONYMOUS_CLASS_DECLARATION
- the dot-based type name
+// * of the type that is being subclassed or implementedFIELD_REF
- the dot-based type name
+// * of the type that declares the field that is referenced
+// * or an anonymous type instantiation ("new X(){}") if it is an anonymous typeFUNCTION_REF
- the dot-based type name
+// * of the type that declares the method that is referenced
+// * or an anonymous type instantiation ("new X(){}") if it is an anonymous typeFUNCTION_DECLARATION
- the dot-based type name
+// * of the type that declares the method that is being
+// * implemented or overriddennull
. Clients must not modify the array
+// * returned.
+// *
+// *
+// * @return the dot-based package name, or
+// * null
if none
+// * @see #getDeclarationSignature()
+// * @see #getSignature()
+// *
+// */
+ public char[] getDeclarationTypeName() {
+ return this.declarationTypeName;
+ }
+//
+// /**
+// * Returns the package name of the method or type
+// * relevant in the context, or null
if none.
+// * +// * This field is available for the following kinds of +// * completion proposals: +// *
FIELD_REF
- the dot-based package name
+// * of the referenced field's typeLOCAL_VARIABLE_REF
- the dot-based package name
+// * of the referenced local variable's typeFUNCTION_REF
- the dot-based package name
+// * of the return type of the method that is referencedFUNCTION_DECLARATION
- the dot-based package name
+// * of the return type of the method that is being implemented
+// * or overriddenPACKAGE_REF
- the dot-based package name
+// * of the package that is referencedTYPE_REF
- the dot-based package name
+// * of the type that is referencedVARIABLE_DECLARATION
- the dot-based package name
+// * of the type of the variable being declarednull
. Clients must not modify the array
+// * returned.
+// *
+// *
+// * @return the package name, or null
if none
+// *
+// * @see #getDeclarationSignature()
+// * @see #getSignature()
+// *
+// */
+// public char[] getPackageName() {
+// return this.packageName;
+// }
+//
+// /**
+// * Returns the type name without the package fragment of the method or type
+// * relevant in the context, or null
if none.
+// * +// * This field is available for the following kinds of +// * completion proposals: +// *
FIELD_REF
- the dot-based type name
+// * of the referenced field's typeLOCAL_VARIABLE_REF
- the dot-based type name
+// * of the referenced local variable's typeFUNCTION_REF
- the dot-based type name
+// * of the return type of the method that is referencedFUNCTION_DECLARATION
- the dot-based type name
+// * of the return type of the method that is being implemented
+// * or overriddenTYPE_REF
- the dot-based type name
+// * of the type that is referencedVARIABLE_DECLARATION
- the dot-based package name
+// * of the type of the variable being declarednull
. Clients must not modify the array
+// * returned.
+// *
+// *
+// * @return the package name, or null
if none
+// *
+// * @see #getDeclarationSignature()
+// * @see #getSignature()
+// *
+// */
+// public char[] getTypeName() {
+// return this.typeName;
+// }
+//
+// /**
+// * Returns the parameter package names of the method
+// * relevant in the context, or null
if none.
+// * +// * This field is available for the following kinds of +// * completion proposals: +// *
ANONYMOUS_CLASS_DECLARATION
- parameter package names
+// * of the constructor that is being invokedFUNCTION_REF
- parameter package names
+// * of the method that is referencedFUNCTION_DECLARATION
- parameter package names
+// * of the method that is being implemented or overriddennull
. Clients must not modify the array
+// * returned.
+// *
+// *
+// * @return the package name, or null
if none
+// *
+// * @see #getDeclarationSignature()
+// * @see #getSignature()
+// *
+// */
+// public char[][] getParameterPackageNames() {
+// return this.parameterPackageNames;
+// }
+//
+// /**
+// * Returns the parameter type names without the package fragment of
+// * the method relevant in the context, or null
if none.
+// * +// * This field is available for the following kinds of +// * completion proposals: +// *
ANONYMOUS_CLASS_DECLARATION
- parameter type names
+// * of the constructor that is being invokedFUNCTION_REF
- parameter type names
+// * of the method that is referencedFUNCTION_DECLARATION
- parameter type names
+// * of the method that is being implemented or overriddennull
. Clients must not modify the array
+// * returned.
+// *
+// *
+// * @return the package name, or null
if none
+// *
+// * @see #getDeclarationSignature()
+// * @see #getSignature()
+// *
+// */
+// public char[][] getParameterTypeNames() {
+// return this.parameterTypeNames;
+// }
+
+ /**
+ * Sets the signature of the function, method, field type, member type,
+ * relevant in the context, or null
if none.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param signature the signature, ornull
if none
+ */
+ public void setSignature(char[] signature) {
+ this.signature = signature;
+ }
+
+ /**
+ * Sets the key of the method, field type, member type,
+ * relevant in the context, or null
if none.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param key the key, ornull
if none
+ */
+ public void setKey(char[] key) {
+ this.key = key;
+ }
+
+ /**
+ * Returns the modifier flags relevant in the context, or
+ * Flags.AccDefault
if none.
+ * + * This field is available for the following kinds of + * completion proposals: + *
ANNOTATION_ATTRIBUT_REF
- modifier flags
+ * of the attribute that is referenced;
+ * ANONYMOUS_CLASS_DECLARATION
- modifier flags
+ * of the constructor that is referencedFIELD_IMPORT
- modifier flags
+ * of the field that is imported.FIELD_REF
- modifier flags
+ * of the field that is referenced;
+ * Flags.AccEnum
can be used to recognize
+ * references to enum constants
+ * KEYWORD
- modifier flag
+ * corresponding to the modifier keywordLOCAL_VARIABLE_REF
- modifier flags
+ * of the local variable that is referencedMETHOD_IMPORT
- modifier flags
+ * of the method that is imported;
+ * FUNCTION_REF
- modifier flags
+ * of the method that is referenced;
+ * Flags.AccAnnotation
can be used to recognize
+ * references to annotation type members
+ * FUNCTION_DECLARATION
- modifier flags
+ * for the method that is being implemented or overriddenTYPE_IMPORT
- modifier flags
+ * of the type that is imported; Flags.AccInterface
+ * can be used to recognize references to interfaces,
+ * Flags.AccEnum
enum types,
+ * and Flags.AccAnnotation
annotation typesTYPE_REF
- modifier flags
+ * of the type that is referenced; Flags.AccInterface
+ * can be used to recognize references to interfaces,
+ * Flags.AccEnum
enum types,
+ * and Flags.AccAnnotation
annotation types
+ * VARIABLE_DECLARATION
- modifier flags
+ * for the variable being declaredPOTENTIAL_METHOD_DECLARATION
- modifier flags
+ * for the method that is being createdFlags.AccDefault
.
+ *
+ *
+ * @return the modifier flags, or
+ * Flags.AccDefault
if none
+ * @see Flags
+ */
+ public int getFlags() {
+ return this.flags;
+ }
+
+ /**
+ * Sets the modifier flags relevant in the context.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param flags the modifier flags, or + *Flags.AccDefault
if none
+ */
+ public void setFlags(int flags) {
+ this.flags = flags;
+ }
+
+ /**
+ * Returns the required completion proposals.
+ * The proposal can be apply only if these required completion proposals are also applied.
+ * If the required proposal aren't applied the completion could create completion problems.
+ *
+ * + * This field is available for the following kinds of + * completion proposals: + *
FIELD_REF
- The allowed required proposals for this kind are:
+ * TYPE_REF
TYPE_IMPORT
FIELD_IMPORT
FUNCTION_REF
- The allowed required proposals for this kind are:
+ * TYPE_REF
TYPE_IMPORT
METHOD_IMPORT
+ * Other kinds of required proposals will be returned in the future, therefore clients of this + * API must allow with {@link CompletionRequestor#setAllowsRequiredProposals(int, int, boolean)} + * only kinds which are in this list to avoid unexpected results in the future. + *
+ *+ * A required completion proposal cannot have required completion proposals. + *
+ * + * @return the required completion proposals, ornull
if none.
+ *
+ * @see CompletionRequestor#setAllowsRequiredProposals(int, int,boolean)
+ *
+ */
+ public CompletionProposal[] getRequiredProposals() {
+ return this.requiredProposals;
+ }
+
+
+ /**
+ * Sets the list of required completion proposals, or null
if none.
+ * + * If not set, defaults to none. + *
+ *+ * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param proposals the list of required completion proposals, or + *null
if none
+ */
+ public void setRequiredProposals(CompletionProposal[] proposals) {
+ this.requiredProposals = proposals;
+ }
+
+ /**
+ * Finds the method or function parameter names.
+ * This information is relevant to method reference (and
+ * method declaration proposals). Returns null
+ * if not available or not relevant.
+ * + * The client must not modify the array returned. + *
+ *+ * Note that this is an expensive thing to compute, which may require + * parsing JavaScript source files, etc. Use sparingly. + *
+ * + * @param monitor the progress monitor, ornull
if none
+ * @return the parameter names, or null
if none
+ * or not available or not relevant
+ */
+ public char[][] findParameterNames(IProgressMonitor monitor) {
+ if (!this.parameterNamesComputed) {
+ this.parameterNamesComputed = true;
+
+ switch(this.completionKind) {
+ case ANONYMOUS_CLASS_DECLARATION:
+ try {
+ this.parameterNames = this.findMethodParameterNames(
+ this.declarationPackageName,
+ this.declarationTypeName,
+ CharOperation.lastSegment(this.declarationTypeName, '.'),
+ Signature.getParameterTypes(this.originalSignature == null ? this.signature : this.originalSignature));
+ } catch(IllegalArgumentException e) {
+ // protection for invalid signature
+ if(this.parameterTypeNames != null) {
+ this.parameterNames = this.createDefaultParameterNames(this.parameterTypeNames.length);
+ } else {
+ this.parameterNames = null;
+ }
+ }
+ break;
+ case METHOD_REF:
+ try {
+ this.parameterNames = this.findMethodParameterNames(
+ this.declarationPackageName,
+ this.declarationTypeName,
+ this.name,
+ Signature.getParameterTypes(this.originalSignature == null ? this.signature : this.originalSignature));
+ } catch(IllegalArgumentException e) {
+ // protection for invalid signature
+ if(this.parameterTypeNames != null) {
+ this.parameterNames = this.createDefaultParameterNames(this.parameterTypeNames.length);
+ } else {
+ this.parameterNames = null;
+ }
+ }
+ break;
+ case METHOD_DECLARATION:
+ try {
+ this.parameterNames = this.findMethodParameterNames(
+ this.declarationPackageName,
+ this.declarationTypeName,
+ this.name,
+ Signature.getParameterTypes(this.originalSignature == null ? this.signature : this.originalSignature));
+ } catch(IllegalArgumentException e) {
+ // protection for invalid signature
+ if(this.parameterTypeNames != null) {
+ this.parameterNames = this.createDefaultParameterNames(this.parameterTypeNames.length);
+ } else {
+ this.parameterNames = null;
+ }
+ }
+ if(this.parameterNames != null) {
+ this.updateCompletion = true;
+ }
+ break;
+ }
+ }
+ return this.parameterNames;
+ }
+
+ /**
+ * Sets the method or function parameter names.
+ * This information is relevant to method reference (and
+ * method declaration proposals).
+ * + * The completion engine creates instances of this class and sets + * its properties; this method is not intended to be used by other clients. + *
+ * + * @param parameterNames the parameter names, ornull
if none
+ */
+ public void setParameterNames(char[][] parameterNames) {
+ this.parameterNames = parameterNames;
+ this.parameterNamesComputed = true;
+ }
+
+ /**
+ * @return true
if this proposal includes parameters,
+ * false
if it does not
+ */
+ public boolean hasParameters() {
+ return this.parameterNames != null && this.parameterNames.length > 0;
+ }
+
+ /**
+ * @return parameter names for this proposal, or null
if they are not set
+ *
+ * @see #findParameterNames(IProgressMonitor)
+ * @see #setParameterNames(char[][])
+ */
+ public char[][] getParamaterNames() {
+ return this.parameterNames;
+ }
+
+ /**
+ * @return type names of the parameters for this proposal, or null
none are set
+ *
+ * @see org.eclipse.wst.jsdt.internal.codeassist.InternalCompletionProposal#getParameterTypeNames()
+ */
+ public char[][] getParameterTypeNames() {
+ return this.parameterTypeNames;
+ }
+
+ /**
+ * Returns the accessibility of the proposal.
+ * + * This field is available for the following kinds of + * completion proposals: + *
TYPE_REF
- accessibility of the type+ * This field is available for the following kinds of + * completion proposals: + *
FUNCTION_REF
- return true
+ * if the referenced method is a constructorFUNCTION_DECLARATION
- return true
+ * if the declared method is a constructorfalse
.
+ *
+ *
+ * @return true
if the proposal is a constructor.
+ */
+ public boolean isConstructor() {
+ return this.isConstructor;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('[');
+ switch(this.completionKind) {
+ case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
+ buffer.append("ANONYMOUS_CLASS_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.FIELD_REF :
+ buffer.append("FIELD_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.KEYWORD :
+ buffer.append("KEYWORD"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.LABEL_REF :
+ buffer.append("LABEL_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.LOCAL_VARIABLE_REF :
+ buffer.append("LOCAL_VARIABLE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_DECLARATION :
+ buffer.append("FUNCTION_DECLARATION"); //$NON-NLS-1$
+ if(this.isConstructor) {
+ buffer.append("+ * This class is intended to be subclassed by clients. + *
+ *+ * The code assist engine normally invokes methods on completion + * requestor in the following sequence: + *
+ * requestor.beginReporting(); + * requestor.acceptContext(context); + * requestor.accept(proposal_1); + * requestor.accept(proposal_2); + * ... + * requestor.endReporting(); + *+ * If, however, the engine is unable to offer completion proposals + * for whatever reason,
completionFailure
is called
+ * with a problem object describing why completions were unavailable.
+ * In this case, the sequence of calls is:
+ * + * requestor.beginReporting(); + * requestor.acceptContext(context); + * requestor.completionFailure(problem); + * requestor.endReporting(); + *+ * In either case, the bracketing
beginReporting
+ * endReporting
calls are always made as well as
+ * acceptContext
call.
+ *
+ *
+ * @see ICodeAssist
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class CompletionRequestor {
+
+ /**
+ * The set of CompletionProposal kinds that this requestor
+ * ignores; 0
means the set is empty.
+ * 1 << completionProposalKind
+ */
+ private int ignoreSet = 0;
+
+ private String[] favoriteReferences;
+
+ /**
+ * The set of CompletionProposal kinds that this requestor
+ * allows for required proposals; 0
means the set is empty.
+ * 1 << completionProposalKind
+ */
+ private int requiredProposalAllowSet[] = null;
+
+ /**
+ * Creates a new completion requestor.
+ * The requestor is interested in all kinds of completion
+ * proposals; none will be ignored.
+ */
+ public CompletionRequestor() {
+ // do nothing
+ }
+
+ /**
+ * Returns whether the given kind of completion proposal is ignored.
+ *
+ * @param completionProposalKind one of the kind constants declared
+ * on CompletionProposal
+ * @return true
if the given kind of completion proposal
+ * is ignored by this requestor, and false
if it is of
+ * interest
+ * @see #setIgnored(int, boolean)
+ * @see CompletionProposal#getKind()
+ */
+ public boolean isIgnored(int completionProposalKind) {
+ if (completionProposalKind < CompletionProposal.FIRST_KIND
+ || completionProposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+completionProposalKind); //$NON-NLS-1$
+ }
+ return 0 != (this.ignoreSet & (1 << completionProposalKind));
+ }
+
+ /**
+ * Sets whether the given kind of completion proposal is ignored.
+ *
+ * @param completionProposalKind one of the kind constants declared
+ * on CompletionProposal
+ * @param ignore true
if the given kind of completion proposal
+ * is ignored by this requestor, and false
if it is of
+ * interest
+ * @see #isIgnored(int)
+ * @see CompletionProposal#getKind()
+ */
+ public void setIgnored(int completionProposalKind, boolean ignore) {
+ if (completionProposalKind < CompletionProposal.FIRST_KIND
+ || completionProposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+completionProposalKind); //$NON-NLS-1$
+ }
+ if (ignore) {
+ this.ignoreSet |= (1 << completionProposalKind);
+ } else {
+ this.ignoreSet &= ~(1 << completionProposalKind);
+ }
+ }
+
+ /**
+ * Returns whether a proposal of a given kind with a required proposal
+ * of the given kind is allowed.
+ *
+ * @param proposalKind one of the kind constants declared
+ * @param requiredProposalKind one of the kind constants declared
+ * on CompletionProposal
+ * @return true
if a proposal of a given kind with a required proposal
+ * of the given kind is allowed by this requestor, and false
+ * if it isn't of interest.
+ * + * By default, all kinds of required proposals aren't allowed. + *
+ * @see #setAllowsRequiredProposals(int, int, boolean) + * @see CompletionProposal#getKind() + * @see CompletionProposal#getRequiredProposals() + * + */ + public boolean isAllowingRequiredProposals(int proposalKind, int requiredProposalKind) { + if (proposalKind < CompletionProposal.FIRST_KIND + || proposalKind > CompletionProposal.LAST_KIND) { + throw new IllegalArgumentException("Unknown kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$ + } + + if (requiredProposalKind < CompletionProposal.FIRST_KIND + || requiredProposalKind > CompletionProposal.LAST_KIND) { + throw new IllegalArgumentException("Unknown required kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$ + } + if (this.requiredProposalAllowSet == null) return false; + + return 0 != (this.requiredProposalAllowSet[proposalKind] & (1 << requiredProposalKind)); + } + + /** + * Sets whether a proposal of a given kind with a required proposal + * of the given kind is allowed. + * + * Currently only a subset of kinds support required proposals. To see what combinations + * are supported you must look at {@link CompletionProposal#getRequiredProposals()} + * documentation. + * + * @param proposalKind one of the kind constants declared + * @param requiredProposalKind one of the kind constants declared + * onCompletionProposal
+ * @param allow true
if a proposal of a given kind with a required proposal
+ * of the given kind is allowed by this requestor, and false
+ * if it isn't of interest
+ * @see #isAllowingRequiredProposals(int, int)
+ * @see CompletionProposal#getKind()
+ * @see CompletionProposal#getRequiredProposals()
+ *
+ */
+ public void setAllowsRequiredProposals(int proposalKind, int requiredProposalKind, boolean allow) {
+ if (proposalKind < CompletionProposal.FIRST_KIND
+ || proposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$
+ }
+ if (requiredProposalKind < CompletionProposal.FIRST_KIND
+ || requiredProposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown required kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$
+ }
+
+ if (this.requiredProposalAllowSet == null) {
+ this.requiredProposalAllowSet = new int[CompletionProposal.LAST_KIND + 1];
+ }
+
+ if (allow) {
+ this.requiredProposalAllowSet[proposalKind] |= (1 << requiredProposalKind);
+ } else {
+ this.requiredProposalAllowSet[proposalKind] &= ~(1 << requiredProposalKind);
+ }
+ }
+
+ /**
+ * Returns the favorite references which are used to compute some completion proposals.
+ *
+ * Currently only on demand type references ("java.util.Arrays.*"
),
+ * references to a static method or a static field are used to compute completion proposals.
+ * Other kind of reference could be used in the future.
+ *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @return favorite imports + * + */ + public String[] getFavoriteReferences() { + return this.favoriteReferences; + } + + /** + * Set the favorite references which will be used to compute some completion proposals. + * A favorite reference is a qualified reference as it can be seen in an import statement.Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param favoriteImports + * + * @see #getFavoriteReferences() + * + */ + public void setFavoriteReferences(String[] favoriteImports) { + this.favoriteReferences = favoriteImports; + } + + /** + * Pro forma notification sent before reporting a batch of + * completion proposals. + *+ * The default implementation of this method does nothing. + * Clients may override. + *
+ */ + public void beginReporting() { + // do nothing + } + + /** + * Pro forma notification sent after reporting a batch of + * completion proposals. + *+ * The default implementation of this method does nothing. + * Clients may override. + *
+ */ + public void endReporting() { + // do nothing + } + + /** + * Notification of failure to produce any completions. + * The problem object explains what prevented completing. + *+ * The default implementation of this method does nothing. + * Clients may override to receive this kind of notice. + *
+ * + * @param problem the problem object + */ + public void completionFailure(IProblem problem) { + // default behavior is to ignore + } + + /** + * Proposes a completion. Has no effect if the kind of proposal + * is being ignored by this requestor. Callers should consider + * checking {@link #isIgnored(int)} before avoid creating proposal + * objects that would only be ignored. + *+ * Similarly, implementers should check + * {@link #isIgnored(int) isIgnored(proposal.getKind())} + * and ignore proposals that have been declared as uninteresting. + * The proposal object passed is only valid for the duration of + * completion operation. + * + * @param proposal the completion proposal + * @exception IllegalArgumentException if the proposal is null + */ + public abstract void accept(CompletionProposal proposal); + + /** + * Propose the context in which the completion occurs. + *
+ * This method is called one and only one time before any call to + * {@link #accept(CompletionProposal)}. + * The default implementation of this method does nothing. + * Clients may override. + *
+ * @param context the completion context + * + */ + public void acceptContext(CompletionContext context) { + // do nothing + } +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CorrectionEngine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CorrectionEngine.java new file mode 100644 index 0000000..c2db585 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/CorrectionEngine.java @@ -0,0 +1,463 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.wst.jsdt.core.compiler.CharOperation; +import org.eclipse.wst.jsdt.core.compiler.IProblem; +import org.eclipse.wst.jsdt.core.compiler.InvalidInputException; +import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons; +import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner; +import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens; +import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.wst.jsdt.internal.core.util.Messages; +import org.eclipse.wst.jsdt.internal.core.util.Util; + +/** + * This class is the entry point for source corrections. + * + * This class is not intended to be subclassed by clients. This class is intended to be instantiated by clients. + * + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class CorrectionEngine implements ProblemReasons { + + /** + * This field is not intended to be used by client. + */ + protected int correctionStart; + /** + * This field is not intended to be used by client. + */ + protected int correctionEnd; + /** + * This field is not intended to be used by client. + */ + protected int prefixLength; + /** + * This field is not intended to be used by client. + */ + protected IJavaScriptUnit compilationUnit; + /** + * This field is not intended to be used by client. + */ + protected ICorrectionRequestor correctionRequestor; + /** + * This field is not intended to be used by client. + */ + protected static final int CLASSES = 0x00000001; + /** + * This field is not intended to be used by client. + */ + protected static final int IMPORT = 0x00000004; + /** + * This field is not intended to be used by client. + */ + protected static final int METHOD = 0x00000008; + /** + * This field is not intended to be used by client. + */ + protected static final int FIELD = 0x00000010; + /** + * This field is not intended to be used by client. + */ + protected static final int LOCAL = 0x00000020; + /** + * This field is not intended to be used by client. + */ + protected int filter; + + /** + * The CorrectionEngine is responsible for computing problem corrections. + * + * @param setting java.util.Map + * set of options used to configure the code correction engine. + * CURRENTLY THERE IS NO CORRECTION SPECIFIC SETTINGS. + */ + public CorrectionEngine(Map setting) { + // settings ignored for now + } + + /** + * Performs code correction for the given marker, + * reporting results to the given correction requestor. + * + * Correction results are answered through a requestor. + * + * @param marker + * the marker which describe the problem to correct. + * @param targetUnit + * replace the compilation unit given by the marker. Ignored if null. + * @param positionOffset + * the offset of position given by the marker. + * @param requestor + * the given correction requestor + * @exception IllegalArgumentException ifrequestor
is null
+ * @exception JavaScriptModelException currently this exception is never thrown, but the opportunity to thrown an exception
+ * when the correction failed is kept for later.
+ */
+ public void computeCorrections(IMarker marker, IJavaScriptUnit targetUnit, int positionOffset, ICorrectionRequestor requestor) throws JavaScriptModelException {
+
+ IJavaScriptElement element = targetUnit == null ? JavaScriptCore.create(marker.getResource()) : targetUnit;
+
+ if(!(element instanceof IJavaScriptUnit))
+ return;
+
+ IJavaScriptUnit unit = (IJavaScriptUnit) element;
+
+ int id = marker.getAttribute(IJavaScriptModelMarker.ID, -1);
+ String[] args = Util.getProblemArgumentsFromMarker(marker.getAttribute(IJavaScriptModelMarker.ARGUMENTS, "")); //$NON-NLS-1$
+ int start = marker.getAttribute(IMarker.CHAR_START, -1);
+ int end = marker.getAttribute(IMarker.CHAR_END, -1);
+
+ computeCorrections(unit, id, start + positionOffset, end + positionOffset, args, requestor);
+ }
+
+ /**
+ * Performs code correction for the given IProblem,
+ * reporting results to the given correction requestor.
+ *
+ * Correction results are answered through a requestor.
+ *
+ * @param problem
+ * the problem which describe the problem to correct.
+ * @param targetUnit
+ * denote the compilation unit in which correction occurs. Cannot be null.
+ * @param requestor
+ * the given correction requestor
+ * @exception IllegalArgumentException if targetUnit
or requestor
is null
+ * @exception JavaScriptModelException currently this exception is never thrown, but the opportunity to thrown an exception
+ * when the correction failed is kept for later.
+ */
+ public void computeCorrections(IProblem problem, IJavaScriptUnit targetUnit, ICorrectionRequestor requestor) throws JavaScriptModelException {
+ if (requestor == null) {
+ throw new IllegalArgumentException(Messages.correction_nullUnit);
+ }
+ this.computeCorrections(
+ targetUnit, problem.getID(),
+ problem.getSourceStart(),
+ problem.getSourceEnd(),
+ problem.getArguments(),
+ requestor);
+ }
+
+ /**
+ * Ask the engine to compute a correction for the specified problem
+ * of the given compilation unit.
+ * Correction results are answered through a requestor.
+ *
+ * @param unit org.eclipse.wst.jsdt.internal.core.ICompilationUnit
+ * the compilation unit.
+ *
+ * @param id int
+ * the id of the problem.
+ *
+ * @param start int
+ * a position in the source where the error begin.
+ *
+ * @param end int
+ * a position in the source where the error finish.
+ *
+ * @param arguments String[]
+ * arguments of the problem.
+ *
+ * @exception IllegalArgumentException if requestor
is null
+ * @exception JavaScriptModelException currently this exception is never thrown, but the opportunity to thrown an exception
+ * when the correction failed is kept for later.
+ */
+ private void computeCorrections(IJavaScriptUnit unit, int id, int start, int end, String[] arguments, ICorrectionRequestor requestor) {
+
+ if(id == -1 || arguments == null || start == -1 || end == -1)
+ return;
+ if (requestor == null) {
+ throw new IllegalArgumentException(Messages.correction_nullRequestor);
+ }
+
+ this.correctionRequestor = requestor;
+ this.correctionStart = start;
+ this.correctionEnd = end;
+ this.compilationUnit = unit;
+
+ String argument = null;
+ try {
+ switch (id) {
+ // Type correction
+ case IProblem.ImportNotFound :
+ this.filter = IMPORT;
+ argument = arguments[0];
+ break;
+ case IProblem.UndefinedType :
+ this.filter = CLASSES;
+ argument = arguments[0];
+ break;
+
+ // Method correction
+ case IProblem.UndefinedMethod :
+ case IProblem.UndefinedFunction :
+ this.filter = METHOD;
+ argument = arguments[1];
+ break;
+
+ // Field and local variable correction
+ case IProblem.UndefinedField :
+ this.filter = FIELD;
+ argument = arguments[0];
+ break;
+ case IProblem.UndefinedName :
+ this.filter = FIELD | LOCAL;
+ argument = arguments[0];
+ break;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return;
+ }
+ if(argument != null) {
+ correct(argument.toCharArray());
+ }
+ }
+
+ private void correct(char[] argument) {
+ try {
+ String source = this.compilationUnit.getSource();
+ Scanner scanner = new Scanner();
+ scanner.setSource(source.toCharArray());
+
+ scanner.resetTo(this.correctionStart, this.correctionEnd);
+ int token = 0;
+ char[] argumentSource = CharOperation.NO_CHAR;
+
+ // search last segment position
+ while(true) {
+ token = scanner.getNextToken();
+ if (token == TerminalTokens.TokenNameEOF) return;
+
+ char[] tokenSource = scanner.getCurrentTokenSource();
+
+ argumentSource = CharOperation.concat(argumentSource, tokenSource);
+ if(!CharOperation.prefixEquals(argumentSource, argument))
+ return;
+
+ if(CharOperation.equals(argument, argumentSource)) {
+ this.correctionStart = scanner.startPosition;
+ this.correctionEnd = scanner.currentPosition;
+ this.prefixLength = CharOperation.lastIndexOf('.', argument) + 1;
+ break;
+ }
+
+ }
+
+ // search completion position
+ int completionPosition = this.correctionStart;
+ scanner.resetTo(completionPosition, this.correctionEnd);
+ int position = completionPosition;
+
+ for (int i = 0; i < 4; i++) {
+ if(scanner.getNextCharAsJavaIdentifierPart()) {
+ completionPosition = position;
+ position = scanner.currentPosition;
+ } else {
+ break;
+ }
+ }
+ Hashtable oldOptions = JavaScriptCore.getOptions();
+ try {
+ Hashtable options = new Hashtable(oldOptions);
+ options.put(JavaScriptCore.CODEASSIST_CAMEL_CASE_MATCH, JavaScriptCore.DISABLED);
+ JavaScriptCore.setOptions(options);
+
+ this.compilationUnit.codeComplete(
+ completionPosition,
+ this.completionRequestor
+ );
+ } finally {
+ JavaScriptCore.setOptions(oldOptions);
+ }
+ } catch (JavaScriptModelException e) {
+ return;
+ } catch (InvalidInputException e) {
+ return;
+ }
+ }
+
+ /**
+ * This field is not intended to be used by client.
+ */
+ protected CompletionRequestor completionRequestor = new CompletionRequestor() {
+ public void accept(CompletionProposal proposal) {
+ switch (proposal.getKind()) {
+ case CompletionProposal.TYPE_REF:
+ if((CorrectionEngine.this.filter & CLASSES) != 0) {
+ char[] completionName = proposal.getCompletion();
+ CorrectionEngine.this.correctionRequestor.acceptClass(
+ proposal.getDeclarationSignature(),
+ Signature.getSignatureSimpleName(proposal.getSignature()),
+ CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
+ proposal.getFlags(),
+ CorrectionEngine.this.correctionStart,
+ CorrectionEngine.this.correctionEnd);
+ } else if((CorrectionEngine.this.filter & IMPORT) != 0) {
+ char[] packageName = proposal.getDeclarationSignature();
+ char[] className = Signature.getSignatureSimpleName(proposal.getSignature());
+ char[] fullName = CharOperation.concat(packageName, className, '.');
+ CorrectionEngine.this.correctionRequestor.acceptClass(
+ packageName,
+ className,
+ CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
+ proposal.getFlags(),
+ CorrectionEngine.this.correctionStart,
+ CorrectionEngine.this.correctionEnd);
+ }
+ break;
+ case CompletionProposal.FIELD_REF:
+ if((CorrectionEngine.this.filter & FIELD) != 0) {
+ char[] declaringSignature = proposal.getDeclarationSignature();
+ char[] signature = proposal.getSignature();
+ CorrectionEngine.this.correctionRequestor.acceptField(
+ Signature.getSignatureQualifier(declaringSignature),
+ Signature.getSignatureSimpleName(declaringSignature),
+ proposal.getName(),
+ Signature.getSignatureQualifier(signature),
+ Signature.getSignatureSimpleName(signature),
+ proposal.getName(),
+ proposal.getFlags(),
+ CorrectionEngine.this.correctionStart,
+ CorrectionEngine.this.correctionEnd);
+ }
+ break;
+ case CompletionProposal.LOCAL_VARIABLE_REF:
+ if((CorrectionEngine.this.filter & LOCAL) != 0) {
+ char[] signature = proposal.getSignature();
+ CorrectionEngine.this.correctionRequestor.acceptLocalVariable(
+ proposal.getName(),
+ Signature.getSignatureQualifier(signature),
+ Signature.getSignatureSimpleName(signature),
+ proposal.getFlags(),
+ CorrectionEngine.this.correctionStart,
+ CorrectionEngine.this.correctionEnd);
+ }
+ break;
+ case CompletionProposal.METHOD_REF:
+ if((CorrectionEngine.this.filter & METHOD) != 0) {
+ char[] declaringSignature = proposal.getDeclarationSignature();
+ char[] signature = proposal.getSignature();
+ char[][] parameterTypeSignatures = Signature.getParameterTypes(signature);
+ int length = parameterTypeSignatures.length;
+ char[][] parameterPackageNames = new char[length][];
+ char[][] parameterTypeNames = new char[length][];
+ for (int i = 0; i < length; i++) {
+ parameterPackageNames[i] = Signature.getSignatureQualifier(parameterTypeSignatures[i]);
+ parameterTypeNames[i] = Signature.getSignatureSimpleName(parameterTypeSignatures[i]);
+ }
+ char[] returnTypeSignature = Signature.getReturnType(signature);
+ CorrectionEngine.this.correctionRequestor.acceptMethod(
+ Signature.getSignatureQualifier(declaringSignature),
+ Signature.getSignatureSimpleName(declaringSignature),
+ proposal.getName(),
+ parameterPackageNames,
+ parameterTypeNames,
+ proposal.findParameterNames(null),
+ Signature.getSignatureQualifier(returnTypeSignature),
+ Signature.getSignatureSimpleName(returnTypeSignature),
+ proposal.getName(),
+ proposal.getFlags(),
+ CorrectionEngine.this.correctionStart,
+ CorrectionEngine.this.correctionEnd);
+ }
+ break;
+ case CompletionProposal.PACKAGE_REF:
+ if((CorrectionEngine.this.filter & (CLASSES | IMPORT)) != 0) {
+ char[] packageName = proposal.getDeclarationSignature();
+ CorrectionEngine.this.correctionRequestor.acceptPackage(
+ packageName,
+ CharOperation.subarray(packageName, CorrectionEngine.this.prefixLength, packageName.length),
+ CorrectionEngine.this.correctionStart,
+ CorrectionEngine.this.correctionEnd);
+ }
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * Return an array of strings which contains one entry per warning token
+ * accepted by the @SuppressWarnings
annotation. This array is
+ * neither null nor empty, it contains at least the String all
.
+ * It should not be modified by the caller (please take a copy if modifications
+ * are needed).@SuppressWarnings
+ * annotation in the JavaScript source code, the effects (if any) may vary from
+ * validator to validator.
+ *
+ * @return an array of strings which contains one entry per warning token
+ * accepted by the @SuppressWarnings
annotation.
+ */
+ public static String[] getAllWarningTokens() {
+ return CompilerOptions.warningTokens;
+ }
+
+ /**
+ * Helper method for decoding problem marker attributes. Returns an array of String arguments
+ * extracted from the problem marker "arguments" attribute, or null
if the marker
+ * "arguments" attribute is missing or ill-formed.
+ *
+ * @param problemMarker
+ * the problem marker to decode arguments from.
+ * @return an array of String arguments, or null
if unable to extract arguments
+ */
+ public static String[] getProblemArguments(IMarker problemMarker){
+ String argumentsString = problemMarker.getAttribute(IJavaScriptModelMarker.ARGUMENTS, null);
+ return Util.getProblemArgumentsFromMarker(argumentsString);
+ }
+
+ /**
+ * Returns a token which can be used to suppress a given warning using
+ * @SuppressWarnings
annotation, for a given problem ID
+ * ({@link IProblem }). If a particular problem is not suppressable,
+ * null
will be returned.
+ *
+ * Note: @SuppressWarnings
can only suppress warnings,
+ * which means that if some problems got promoted to ERROR using custom compiler
+ * settings ({@link IJavaScriptProject#setOption(String, String)}), the
+ * @SuppressWarnings
annotation will be ineffective.
+ *
+ * Note: @SuppressWarnings
can be argumented with
+ * "all"
so as to suppress all possible warnings at once.
+ *
+ * Note: The tokens returned are not necessarily standardized across JavaScript + * validators. If you were to use one of these tokens in an @SuppressWarnings + * annotation in the JavaScript source code, the effects (if any) may vary from + * validator to validator. + *
+ * @param problemID + * the ID of a given warning to suppress + * @return a String which can be used in@SuppressWarnings
annotation,
+ * or null
if unable to suppress this warning.
+ */
+ public static String getWarningToken(int problemID){
+ long irritant = ProblemReporter.getIrritant(problemID);
+ if (irritant != 0) {
+ return CompilerOptions.warningTokenFromIrritant(irritant);
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ElementChangedEvent.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ElementChangedEvent.java
new file mode 100644
index 0000000..d29b576
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ElementChangedEvent.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.util.EventObject;
+
+/**
+ * An element changed event describes a change to the structure or contents
+ * of a tree of JavaScript elements. The changes to the elements are described by
+ * the associated delta object carried by this event.
+ * + * This class is not intended to be instantiated or subclassed by clients. + * Instances of this class are automatically created by the JavaScript model. + *
+ * + * @see IElementChangedListener + * @see IJavaScriptElementDelta + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class ElementChangedEvent extends EventObject { + + /** + * Event type constant (bit mask) indicating an after-the-fact + * report of creations, deletions, and modifications + * to one or more JavaScript element(s) expressed as a hierarchical + * java element delta as returned bygetDelta()
.
+ *
+ * Note: this notification occurs during the corresponding POST_CHANGE
+ * resource change notification, and contains a full delta accounting for
+ * any JavaScriptModel operation and/or resource change.
+ *
+ * @see IJavaScriptElementDelta
+ * @see org.eclipse.core.resources.IResourceChangeEvent
+ * @see #getDelta()
+ */
+ public static final int POST_CHANGE = 1;
+
+ /**
+ * Event type constant (bit mask) indicating an after-the-fact
+ * report of creations, deletions, and modifications
+ * to one or more JavaScript element(s) expressed as a hierarchical
+ * java element delta as returned by getDelta
.
+ *
+ * Note: this notification occurs as a result of a working copy reconcile
+ * operation.
+ *
+ * @see IJavaScriptElementDelta
+ * @see org.eclipse.core.resources.IResourceChangeEvent
+ * @see #getDelta()
+ */
+ public static final int POST_RECONCILE = 4;
+
+ private static final long serialVersionUID = -8947240431612844420L; // backward compatible
+
+ /*
+ * Event type indicating the nature of this event.
+ * It can be a combination either:
+ * - POST_CHANGE
+ * - PRE_AUTO_BUILD
+ * - POST_RECONCILE
+ */
+ private int type;
+
+ /**
+ * Creates an new element changed event (based on a IJavaScriptElementDelta
).
+ *
+ * @param delta the JavaScript element delta.
+ * @param type the type of delta (ADDED, REMOVED, CHANGED) this event contains
+ */
+ public ElementChangedEvent(IJavaScriptElementDelta delta, int type) {
+ super(delta);
+ this.type = type;
+ }
+ /**
+ * Returns the delta describing the change.
+ *
+ * @return the delta describing the change
+ */
+ public IJavaScriptElementDelta getDelta() {
+ return (IJavaScriptElementDelta) this.source;
+ }
+
+ /**
+ * Returns the type of event being reported.
+ *
+ * @return one of the event type constants
+ * @see #POST_CHANGE
+ * @see #POST_RECONCILE
+ */
+ public int getType() {
+ return this.type;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Flags.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Flags.java
new file mode 100644
index 0000000..751e5ef
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Flags.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - added constant AccDefault
+ * IBM Corporation - added constants AccBridge and AccVarargs for J2SE 1.5
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+
+/**
+ * Utility class for decoding modifier flags in JavaScript elements.
+ * + * This class provides static methods only; it is not intended to be + * instantiated or subclassed by clients. + *
+ * + * @see IMember#getFlags() + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class Flags { + + /** + * Constant representing the absence of any flag + */ + public static final int AccDefault = ClassFileConstants.AccDefault; + /** + * Public access flag. + * + * This flag only applies to ECMAScript 4 which is not yet supported + */ + public static final int AccPublic = ClassFileConstants.AccPublic; + /** + * Private access flag. + * + * This flag only applies to ECMAScript 4 which is not yet supported + */ + public static final int AccPrivate = ClassFileConstants.AccPrivate; + /** + * Protected access flag. + * + * This flag only applies to ECMAScript 4 which is not yet supported + */ + public static final int AccProtected = ClassFileConstants.AccProtected; + /** + * Static access flag. + */ + public static final int AccStatic = ClassFileConstants.AccStatic; + /** + * Abstract property flag. + * + * This flag only applies to ECMAScript 4 which is not yet supported + */ + public static final int AccAbstract = ClassFileConstants.AccAbstract; + /** + * Super property flag. + * + * This flag only applies to ECMAScript 4 which is not yet supported + */ + public static final int AccSuper = ClassFileConstants.AccSuper; + /** + * Deprecated property flag. + */ + public static final int AccDeprecated = ClassFileConstants.AccDeprecated; + + /**= + * Varargs method property + * Used to flag variable arity method declarations. + * + * This flag only applies to ECMAScript 4 which is not yet supported + */ + public static final int AccVarargs = ClassFileConstants.AccVarargs; + + /** + * Not instantiable. + */ + private Flags() { + // Not instantiable + } + /** + * Returns whether the given integer includes theabstract
modifier.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param flags the flags + * @returntrue
if the abstract
modifier is included
+ */
+ public static boolean isAbstract(int flags) {
+ return (flags & AccAbstract) != 0;
+ }
+ /**
+ * Returns whether the given integer includes the indication that the
+ * element is deprecated (@deprecated
tag in jsdoc comment).
+ *
+ * @param flags the flags
+ * @return true
if the element is marked as deprecated
+ */
+ public static boolean isDeprecated(int flags) {
+ return (flags & AccDeprecated) != 0;
+ }
+ /*
+ * Returns whether the given integer does not include one of the
+ * public
, private
, or protected
flags.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param flags the flags + * @returntrue
if no visibility flag is set
+ */
+ public static boolean isPackageDefault(int flags) {
+ return (flags & (AccPublic | AccProtected | AccPrivate)) == 0;
+ }
+ /**
+ * Returns whether the given integer includes the private
modifier.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param flags the flags + * @returntrue
if the private
modifier is included
+ */
+ public static boolean isPrivate(int flags) {
+ return (flags & AccPrivate) != 0;
+ }
+ /**
+ * Returns whether the given integer includes the protected
modifier.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param flags the flags + * @returntrue
if the protected
modifier is included
+ */
+ public static boolean isProtected(int flags) {
+ return (flags & AccProtected) != 0;
+ }
+ /**
+ * Returns whether the given integer includes the public
modifier.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param flags the flags + * @returntrue
if the public
modifier is included
+ */
+ public static boolean isPublic(int flags) {
+ return (flags & AccPublic) != 0;
+ }
+ /**
+ * Returns whether the given integer includes the static
modifier.
+ *
+ * @param flags the flags
+ * @return true
if the static
modifier is included
+ */
+ public static boolean isStatic(int flags) {
+ return (flags & AccStatic) != 0;
+ }
+ /**
+ * Returns whether the given integer includes the super
modifier.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param flags the flags + * @returntrue
if the super
modifier is included
+ */
+ public static boolean isSuper(int flags) {
+ return (flags & AccSuper) != 0;
+ }
+
+ /*
+ * Returns whether the given integer has the AccVarargs
+ * bit set.
+ *
+ * @param flags the flags
+ * @return true
if the AccVarargs
flag is included
+ * @see #AccVarargs
+ */
+ public static boolean isVarargs(int flags) {
+ return (flags & AccVarargs) != 0;
+ }
+
+ /**
+ * Returns a standard string describing the given modifier flags.
+ * Only modifier flags are included in the output; deprecated,
+ * synthetic, bridge, etc. flags are ignored.
+ * + * The flags are output in the following order: + *
+ *+ * + *public
protected
private
+ *static
+ *abstract
final
native
synchronized
transient
volatile
strictfp
+ *
+ * Examples results: + *
+ *+ * + * + * @param flags the flags + * @return the standard string representation of the given flags + */ + public static String toString(int flags) { + StringBuffer sb = new StringBuffer(); + + if (isPublic(flags)) + sb.append("public "); //$NON-NLS-1$ + if (isPrivate(flags)) + sb.append("private "); //$NON-NLS-1$ + if (isStatic(flags)) + sb.append("static "); //$NON-NLS-1$ + if (isAbstract(flags)) + sb.append("abstract "); //$NON-NLS-1$ + + int len = sb.length(); + if (len == 0) + return ""; //$NON-NLS-1$ + sb.setLength(len - 1); + return sb.toString(); + } +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IAccessRule.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IAccessRule.java new file mode 100644 index 0000000..e6ff7b2 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IAccessRule.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import org.eclipse.core.runtime.IPath; + +/** + * Describes an access rule to source and class files on a includepath entry. + * An access rule is composed of a file pattern and a kind (accessible, + * non accessible, or discouraged). + *"public static final"
+ *"private native"
+ *
+ * On a given includepath entry, the access rules are considered in the order given
+ * when the entry was created. When a source matches an access
+ * rule's pattern, the access rule's kind define whether the file is considered
+ * accessible, non accessible, or its access is discouraged. If the source
+ * file doesn't match any accessible rule, it is considered accessible. A source
+ * file that is not accessible or discouraged can still be refered to but it is tagged as being not
+ * accessible - the JavaScript validator will create a problem marker for example.
+ * The severity of the marker created from a non accessible rule is controled through
+ * the {@link JavaScriptCore#COMPILER_PB_FORBIDDEN_REFERENCE} compiler option.
+ * The severity of the marker created from a discouraged rule is controled through
+ * the {@link JavaScriptCore#COMPILER_PB_DISCOURAGED_REFERENCE} compiler option.
+ * Note this is different from inclusion and exclusion patterns on source includepath entries,
+ * where a source file that is excluded is not even validated.
+ * Files patterns look like relative file paths with wildcards and are interpreted relative
+ * to each entry's path.
+ * File patterns are case-sensitive and they can contain '**', '*' or '?' wildcards (see
+ * {@link IIncludePathEntry#getExclusionPatterns()} for the full description
+ * of their syntax and semantics).
+ * Note that file patterns must not include the file extension.
+ * com/xyz/tests/MyClass
is a valid file pattern, whereas
+ * com/xyz/tests/MyClass.class
is not valid.
+ *
Flag indicating that whether a type matching this rule should be ignored iff a type with + * the same qualified name can be found on a later includepath entry with a better + * accessibility.
+ *E.g. if a type p.X matches a rule K_NON_ACCESSIBLE | IGNORE_IF_BETTER + * on a library entry 'lib1' and another type p.X also matches a rule + * K_DISCOURAGED on library entry 'lib2' ('lib2' being after 'lib1' on the + * includepath), then p.X from 'lib2' will be used and reported as + * discouraged.
+ * + */ + int IGNORE_IF_BETTER = 0x100; + + /** + * Returns the file pattern for this access rule. + * + * @return the file pattern for this access rule + */ + IPath getPattern(); + + /** + * Returns the kind of this access rule (one of {@link #K_ACCESSIBLE}, {@link #K_NON_ACCESSIBLE} + * or {@link #K_DISCOURAGED}). + * + * @return the kind of this access rule + */ + int getKind(); + + /** + *Returns whether a type matching this rule should be ignored iff a type with + * the same qualified name can be found on a later includepath entry with a better + * accessibility.
+ *E.g. if a type p.X matches a rule K_NON_ACCESSIBLE | IGNORE_IF_BETTER + * on a library entry 'lib1' and another type p.X also matches a rule + * K_DISCOURAGED on library entry 'lib2' ('lib2' being after 'lib1' on the + * includepath), then p.X from 'lib2' will be used and reported as + * discouraged.
+ * + * @return whether a type matching this rule should be ignored iff a type + * with the same qualified name can be found on a later includepath + * entry with a better accessibility + */ + boolean ignoreIfBetter(); + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBuffer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBuffer.java new file mode 100644 index 0000000..b46fb92 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBuffer.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * A buffer contains the text contents of a resource. It is not language-specific. + * The contents may be in the process of being edited, differing from the actual contents of the + * underlying resource. A buffer has an owner, which is anIOpenable
.
+ * If a buffer does not have an underlying resource, saving the buffer has no effect.
+ * Buffers can be read-only.
+ *
+ * Note that javaScript model operations that manipulate an IBuffer
(for example,
+ * IType.createMethod(...)
) ensures that the same line delimiter
+ * (either "\n"
or "\r"
or "\r\n"
) is
+ * used across the whole buffer. Thus these operations may change the line delimiter(s)
+ * included in the string to be append, or replaced.
+ * However implementers of this interface should be aware that other clients of IBuffer
+ * might not do such transformations beforehand.
+ *
+ * This interface may be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IBuffer { + +/** + * Adds the given listener for changes to this buffer. + * Has no effect if an identical listener is already registered or if the buffer + * is closed. + * + * @param listener the listener of buffer changes + */ +public void addBufferChangedListener(IBufferChangedListener listener); +/** + * Appends the given character array to the contents of the buffer. + * This buffer will now have unsaved changes. + * Any client can append to the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *+ * Has no effect if this buffer is read-only or if the buffer is closed. + * + * @param text the given character array to append to contents of the buffer + */ +public void append(char[] text); +/** + * Appends the given string to the contents of the buffer. + * This buffer will now have unsaved changes. + * Any client can append to the contents of the buffer, not just the owner of the buffer. + * Reports a buffer changed event. + *
+ * Has no effect if this buffer is read-only or if the buffer is closed.
+ *
+ * @param text the String
to append to the contents of the buffer
+ */
+public void append(String text);
+/**
+ * Closes the buffer. Any unsaved changes are lost. Reports a buffer changed event
+ * with a 0 offset and a 0 length. When this event is fired, the buffer should already
+ * be closed.
+ *
+ * Further operations on the buffer are not allowed, except for close. If an + * attempt is made to close an already closed buffer, the second attempt has no effect. + */ +public void close(); +/** + * Returns the character at the given position in this buffer. + *
+ * The returned value is undefined if the buffer is closed.
+ *
+ * @param position a zero-based source offset in this buffer
+ * @return the character at the given position in this buffer
+ */
+public char getChar(int position);
+/**
+ * Returns the contents of this buffer as a character array, or null
if
+ * the buffer has not been initialized.
+ *
+ * Callers should make no assumption about whether the returned character array + * is or is not the genuine article or a copy. In other words, if the client + * wishes to change this array, they should make a copy. Likewise, if the + * client wishes to hang on to the array in its current state, they should + * make a copy. + *
+ * The returned value is undefined if the buffer is closed.
+ *
+ * @return the characters contained in this buffer
+ */
+public char[] getCharacters();
+/**
+ * Returns the contents of this buffer as a String
. Like all strings,
+ * the result is an immutable value object., It can also answer null
if
+ * the buffer has not been initialized.
+ *
+ * The returned value is undefined if the buffer is closed.
+ *
+ * @return the contents of this buffer as a String
+ */
+public String getContents();
+/**
+ * Returns number of characters stored in this buffer.
+ *
+ * The returned value is undefined if the buffer is closed. + * + * @return the number of characters in this buffer + */ +public int getLength(); +/** + * Returns the JavaScript openable element owning of this buffer. + * + * @return the openable element owning this buffer + */ +public IOpenable getOwner(); +/** + * Returns the given range of text in this buffer. + *
+ * The returned value is undefined if the buffer is closed.
+ *
+ * @param offset the zero-based starting offset
+ * @param length the number of characters to retrieve
+ * @return the given range of text in this buffer
+ */
+public String getText(int offset, int length);
+/**
+ * Returns the underlying resource for which this buffer was opened,
+ * or null
if this buffer was not opened on a resource.
+ *
+ * @return the underlying resource for this buffer, or null
+ * if none.
+ */
+public IResource getUnderlyingResource();
+/**
+ * Returns whether this buffer has been modified since it
+ * was opened or since it was last saved.
+ * If a buffer does not have an underlying resource, this method always
+ * returns true
.
+ *
+ * NOTE: when a buffer does not have unsaved changes, the model may decide to close it + * to claim some memory back. If the associated element needs to be reopened later on, its + * buffer factory will be requested to create a new buffer. + *
+ * @return aboolean
indicating presence of unsaved changes (in
+ * the absence of any underlying resource, it will always return true
).
+ */
+public boolean hasUnsavedChanges();
+/**
+ * Returns whether this buffer has been closed.
+ *
+ * @return a boolean
indicating whether this buffer is closed.
+ */
+public boolean isClosed();
+/**
+ * Returns whether this buffer is read-only.
+ *
+ * @return a boolean
indicating whether this buffer is read-only
+ */
+public boolean isReadOnly();
+/**
+ * Removes the given listener from this buffer.
+ * Has no affect if an identical listener is not registered or if the buffer is closed.
+ *
+ * @param listener the listener
+ */
+public void removeBufferChangedListener(IBufferChangedListener listener);
+/**
+ * Replaces the given range of characters in this buffer with the given text.
+ * position
and position + length
must be in the range [0, getLength()].
+ * length
must not be negative.
+ *
+ * Has no effect if this buffer is read-only or if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a character array
+ */
+public void replace(int position, int length, char[] text);
+/**
+ * Replaces the given range of characters in this buffer with the given text.
+ * position
and position + length
must be in the range [0, getLength()].
+ * length
must not be negative.
+ *
+ * Has no effect if this buffer is read-only or if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a String
+ */
+public void replace(int position, int length, String text);
+/**
+ * Saves the contents of this buffer to its underlying resource. If
+ * successful, this buffer will have no unsaved changes.
+ * The buffer is left open. Saving a buffer with no unsaved
+ * changes has no effect - the underlying resource is not changed.
+ * If the buffer does not have an underlying resource or is read-only, this
+ * has no effect.
+ *
+ * The force
parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If false
is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no
+ * unintended data loss; it is the recommended setting.
+ * However, if true
is specified, an attempt will be made
+ * to write a corresponding file in the local file system,
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked
+ * as being local (even if it wasn't before).
+ *
+ * Has no effect if this buffer is read-only or if the buffer is closed.
+ *
+ * @param progress the progress monitor to notify
+ * @param force a boolean
flag indicating how to deal with resource
+ * inconsistencies.
+ *
+ * @exception JavaScriptModelException if an error occurs writing the buffer
+ * to the underlying resource
+ *
+ * @see org.eclipse.core.resources.IFile#setContents(java.io.InputStream, boolean, boolean, org.eclipse.core.runtime.IProgressMonitor)
+ */
+public void save(IProgressMonitor progress, boolean force) throws JavaScriptModelException;
+/**
+ * Sets the contents of this buffer to the given character array.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ *
+ * Equivalent to replace(0,getLength(),contents)
.
+ *
+ * Has no effect if this buffer is read-only or if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a character array
+ */
+public void setContents(char[] contents);
+/**
+ * Sets the contents of this buffer to the given String
.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ *
+ * Equivalent to replace(0,getLength(),contents)
.
+ *
+ * Has no effect if this buffer is read-only or if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a String
+ */
+public void setContents(String contents);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBufferChangedListener.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBufferChangedListener.java
new file mode 100644
index 0000000..ed5c634
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBufferChangedListener.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * A listener, which gets notified when the contents of a specific buffer
+ * have changed, or when the buffer is closed.
+ * When a buffer is closed, the listener is notified after the buffer has been closed.
+ * A listener is not notified when a buffer is saved.
+ *
+ * This interface may be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. +*/ +public interface IBufferChangedListener { + + /** + * Notifies that the given event has occurred. + * + * @param event the change event + */ + public void bufferChanged(BufferChangedEvent event); +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBufferFactory.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBufferFactory.java new file mode 100644 index 0000000..96e9d33 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IBufferFactory.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +/** + * A factory that createsIBuffer
s for openables.
+ * + * This interface may be implemented by clients. + *
+ * @deprecated Use {@link WorkingCopyOwner} instead + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IBufferFactory { + + /** + * Creates a buffer for the given owner. + * The new buffer will be initialized with the contents of the owner + * if and only if it was not already initialized by the factory (a buffer is uninitialized if + * its content isnull
).
+ *
+ * @param owner the owner of the buffer
+ * @return the newly created buffer
+ * @see IBuffer
+ */
+ IBuffer createBuffer(IOpenable owner);
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IClassFile.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IClassFile.java
new file mode 100644
index 0000000..c98e698
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IClassFile.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+
+/**
+ * Represents an entire non-editable JavaScript file.
+ * non-editable JavaScript file elements need to be opened before they can be navigated.
+ * If a file cannot be parsed, its structure remains unknown. Use
+ * IJavaScriptElement.isStructureKnown
to determine whether this is the
+ * case.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. +*/ + +public interface IClassFile extends ITypeRoot { + +/** + * Returns the bytes contained in this file. + * + * @return the bytes contained in this file + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ +byte[] getBytes() throws JavaScriptModelException; + +/** + * Returns the first type contained in this file. + * This is a handle-only method. The type may or may not exist. + * + * @return the type contained in this file + * + */ +IType getType(); +public IType[] getTypes() throws JavaScriptModelException ; + + +/* + * Returns whether this type is edit. This is not guaranteed to be + * instantaneous, as it may require parsing the underlying file. + * + * @returntrue
if the file represents a class.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+boolean isClass() throws JavaScriptModelException;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ICodeAssist.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ICodeAssist.java
new file mode 100644
index 0000000..f8d85da
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ICodeAssist.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * Common protocol for JavaScript elements that support source code assist and code
+ * resolve.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ICodeAssist { + + /** + * Performs code completion at the given offset position in this javaScript unit, + * reporting results to the given completion requestor. Theoffset
+ * is the 0-based index of the character, after which code assist is desired.
+ * An offset
of -1 indicates to code assist at the beginning of this
+ * javaScript unit.
+ * + * + * @param offset the given offset position + * @param requestor the given completion requestor + * @exception JavaScriptModelException if code assist could not be performed. Reasons include:
requestor
is null
+ */
+ void codeComplete(int offset, CompletionRequestor requestor)
+ throws JavaScriptModelException;
+
+ /**
+ * Performs code completion at the given offset position in this javaScript unit,
+ * reporting results to the given completion requestor. The offset
+ * is the 0-based index of the character, after which code assist is desired.
+ * An offset
of -1 indicates to code assist at the beginning of this
+ * javaScript unit.
+ * It considers types in the working copies with the given owner first. In other words,
+ * the owner's working copies will take precedence over their original javaScript units
+ * in the workspace.
+ * + * Note that if a working copy is empty, it will be as if the original javaScript + * unit had been deleted. + *
+ * + * @param offset the given offset position + * @param requestor the given completion requestor + * @param owner the owner of working copies that take precedence over their original javaScript units + * @exception JavaScriptModelException if code assist could not be performed. Reasons include:requestor
is null
+ */
+ void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner)
+ throws JavaScriptModelException;
+
+ /**
+ * Returns the JavaScript elements corresponding to the given selected text in this javaScript unit.
+ * The offset
is the 0-based index of the first selected character.
+ * The length
is the number of selected characters.
+ *
+ * Note that if the length
is 0 and the offset
is inside an identifier
+ * or the index just after an identifier then this identifier is considered as the selection.
+ *
offset
is the 0-based index of the first selected character.
+ * The length
is the number of selected characters.
+ * It considers types in the working copies with the given owner first. In other words,
+ * the owner's working copies will take precedence over their original javaScript units
+ * in the workspace.
+ *
+ * Note that if the length
is 0 and the offset
is inside an identifier
+ * or the index just after an identifier then this identifier is considered as the selection.
+ *
+ * Note that if a working copy is empty, it will be as if the original javaScript + * unit had been deleted. + *
+ * + * @param offset the given offset position + * @param length the number of selected characters + * @param owner the owner of working copies that take precedence over their original javaScript units + * @return the JavaScript elements corresponding to the given selected text + * + * @exception JavaScriptModelException if code resolve could not be performed. Reasons include: + *null
for a constructor.
+ * @param correctionName The correction for the method.
+ * Can include zero, one or two brackets. If the closing bracket is included, then the cursor should be placed before it.
+ * @param modifiers The modifiers of this method.
+ * @param correctionStart The start position of insertion of the correction of this method.
+ * @param correctionEnd The end position of insertion of the correction of this method.
+ *
+ * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ */
+void acceptMethod(
+ char[] declaringTypePackageName,
+ char[] declaringTypeName,
+ char[] selector,
+ char[][] parameterPackageNames,
+ char[][] parameterTypeNames,
+ char[][] parameterNames,
+ char[] returnTypePackageName,
+ char[] returnTypeName,
+ char[] correctionName,
+ int modifiers,
+ int correctionStart,
+ int correctionEnd);
+/**
+ * Notification of a package correction.
+ *
+ * @param packageName The package name.
+ * @param correctionName The correction for the package.
+ * Can include '.*;' for imports.
+ * @param correctionStart The start position of insertion of the correction of this package.
+ * @param correctionEnd The end position of insertion of the correction of this package.
+ *
+ * This Method only applies to ECMAScript 4 which is not yet supported
+ */
+void acceptPackage(
+ char[] packageName,
+ char[] correctionName,
+ int correctionStart,
+ int correctionEnd);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IElementChangedListener.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IElementChangedListener.java
new file mode 100644
index 0000000..2c2e421
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IElementChangedListener.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * An element changed listener receives notification of changes to JavaScript elements
+ * maintained by the JavaScript model.
+ * + * This interface may be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IElementChangedListener { + +/** + * Notifies that one or more attributes of one or more JavaScript elements have changed. + * The specific details of the change are described by the given event. + * + * @param event the change event + */ +public void elementChanged(ElementChangedEvent event); +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IField.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IField.java new file mode 100644 index 0000000..a7b5862 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IField.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * IBM Corporation - added J2SE 1.5 support + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +/** + * Represents a field declared in a type or a var declared at the file scope. + *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IField extends IMember { +/** + * Returns the simple name of this field. + * @return the simple name of this field. + */ +String getElementName(); +/** + * Returns the binding key for this field. A binding key is a key that uniquely + * identifies this field. It allows access to generic info for parameterized + * fields. + * + * @return the binding key for this field + * @see org.eclipse.wst.jsdt.core.dom.IBinding#getKey() + * @see BindingKey + */ +String getKey(); +/** + * Returns the type signature of this field. + *+ * The type signature may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @return the type signature of this field + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @see Signature + */ +String getTypeSignature() throws JavaScriptModelException; + +/** + * Returns whether this field represents a resolved field. + * If a field is resoved, its key contains resolved information. + * + * @return whether this field represents a resolved field. + */ +boolean isResolved(); + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IFunction.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IFunction.java new file mode 100644 index 0000000..beedf90 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IFunction.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * IBM Corporation - added J2SE 1.5 support + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +/** + * Represents a function or a method (or constructor) declared in a type. + *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IFunction extends IMember { +/** + * Returns the simple name of this function or method. + * For a constructor, this returns the simple name of the declaring type. + * Note: This holds whether the constructor appears in a source or binary type + * This is a handle-only method. + * @return the simple name of this method + */ +String getElementName(); +/** + * Returns the number of parameters of this method. + * This is a handle-only method. + * + * @return the number of parameters of this method + */ +int getNumberOfParameters(); +/** + * Returns the binding key for this method. A binding key is a key that uniquely + * identifies this method. It allows access to generic info for parameterized + * methods. + * + * @return the binding key for this method + * @see org.eclipse.wst.jsdt.core.dom.IBinding#getKey() + * @see BindingKey + */ +String getKey(); +/** + * Returns the names of parameters in this method. + * Returns an empty array if this method has no parameters. + * + *For example, a method declared as function foo( text, length)
+ * would return the array {"text","length"}
.
+ *
+ * The type signatures may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @return the type signatures for the parameters of this method, an empty array if this method has no parameters + * @see Signature + */ +String[] getParameterTypes(); +/** + * Returns the names of parameters in this method. + * Returns an empty array if this method has no parameters. + * + *For example, a method declared as function foo( text, length)
+ * would return the array {"text","length"}
. For the same method in a
+ * binary, this would return {"arg0", "arg1"}
.
+ *
+ * Until EMCAScript 4 is supported, types are inferred by analying the code, and are not necessarily accurate. + *
+ *
+ * For example, a source method declared as function getName(){return "abc"}
+ * would return "QString;"
.
+ *
+ * The type signature may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return the type signature of the return value of this method, void for constructors + * @see Signature + */ +String getReturnType() throws JavaScriptModelException; +/** + * Returns the signature of this method. This includes the signatures for the + * parameter types and return type, but does not include the method name, + * exception types, or type parameters. + *
+ * For example, a source method declared as public void foo(String text, int length)
+ * would return "(QString;I)V"
.
+ *
+ * The type signatures embedded in the method signature may be either unresolved + * (for source types) or resolved (for binary types), and either basic (for + * basic types) or rich (for parameterized types). See {@link Signature} for + * details. + *
+ * + * @return the signature of this method + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @see Signature + */ +String getSignature() throws JavaScriptModelException; +/** + * Returns whether this method is a constructor. + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @return true if this method is a constructor, false otherwise + */ +boolean isConstructor() throws JavaScriptModelException; + +/** + * Returns whether this method represents a resolved method. + * If a method is resoved, its key contains resolved information. + * + * @return whether this method represents a resolved method. + */ +boolean isResolved(); +/** + * Returns whether this method is similar to the given method. + * Two methods are similar if: + *IJavaScriptUnit
+ * or an IType
).
+ *
+ * + * This interface is not intended to be implemented by clients. + *
+ * + *+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + *
+ + */ +public interface IFunctionContainer { + + +/** + * Returns the field with the specified name + * in this type (for example,"bar"
).
+ * This is a handle-only method. The field may or may not exist.
+ *
+ * @param name the given name
+ * @return the field with the specified name in this type
+ */
+IField getField(String name);
+/**
+ * Returns the fields declared by this type or javascript file.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the fields declared by this type or file
+ */
+IField[] getFields() throws JavaScriptModelException;
+
+/**
+ * Returns the method with the specified name and parameter types
+ * in this type (for example, "foo", {"I", "QString;"}
).
+ * To get the handle for a constructor, the name specified must be the
+ * simple name of the enclosing type.
+ * This is a handle-only method. The method may or may not be present.
+ * + * The type signatures may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @param name the given name + * @param parameterTypeSignatures the given parameter types + * @return the method with the specified name and parameter types in this type + */ +IFunction getFunction(String name, String[] parameterTypeSignatures); + +/** + * Returns the methods and constructors declared by this type or file. + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return the methods and constructors declared by this type + */ +IFunction[] getFunctions() throws JavaScriptModelException; + +/** + * Returns the type with the specified name + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return the type with the specified name in this file + */ +IType getType(String name); + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IImportContainer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IImportContainer.java new file mode 100644 index 0000000..d89a141 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IImportContainer.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +/** + * Represents an import container is a child of a JavaScript unit that contains + * all (and only) the import declarations. If a JavaScript unit has no import + * declarations, no import container will be present. + *+ * This interface is not intended to be implemented by clients. + *
+ * + * This Interface only applies to ECMAScript 4 which is not yet supported + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IImportContainer extends IJavaScriptElement, IParent, ISourceReference { +/** + * Returns the first import declaration in this import container with the given name. + * This is a handle-only method. The import declaration may or may not exist. + * + * @param name the given name + * + * @return the first import declaration in this import container with the given name + */ +IImportDeclaration getImport(String name); +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IImportDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IImportDeclaration.java new file mode 100644 index 0000000..179bc32 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IImportDeclaration.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * IBM Corporation - added J2SE 1.5 support + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +/** + * Represents an import declaration in JavaScript unit. + *+ * This interface is not intended to be implemented by clients. + *
+ * + * This Interface only applies to ECMAScript 4 which is not yet supported + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IImportDeclaration extends IJavaScriptElement, ISourceReference, ISourceManipulation { +/** + * Returns the name that has been imported. + * + * @return the name that has been imported + */ +String getElementName(); +/** + * Returns the modifier flags for this import. The flags can be examined using class + *Flags
. Only the static flag is meaningful for import declarations.
+ *
+ * @return the modifier flags for this import
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @see Flags
+ */
+int getFlags() throws JavaScriptModelException;
+
+/*
+ * Returns whether the import is on-demand. An import is on-demand if it ends
+ * with ".*"
.
+ * @return true if the import is on-demand, false otherwise
+ */
+boolean isOnDemand();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IIncludePathAttribute.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IIncludePathAttribute.java
new file mode 100644
index 0000000..d3d2b92
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IIncludePathAttribute.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.wst.jsdt.internal.core.ClasspathAttribute;
+
+/**
+ * A includepath attribute defines a name/value pair that can be persisted with a includepath entry. Such an attribute
+ * can be created using the factory method {@link JavaScriptCore#newIncludepathAttribute(String, String) newClasspathAttribute(String name, String value)}.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * @see JavaScriptCore#newContainerEntry( + * org.eclipse.core.runtime.IPath containerPath, + * IAccessRule[] accessRules, + * IIncludePathAttribute[] extraAttributes, + * boolean isExported) + * @see JavaScriptCore#newLibraryEntry( + * org.eclipse.core.runtime.IPath path, + * org.eclipse.core.runtime.IPath sourceAttachmentPath, + * org.eclipse.core.runtime.IPath sourceAttachmentRootPath, + * IAccessRule[] accessRules, + * IIncludePathAttribute[] extraAttributes, + * boolean isExported) + * @see JavaScriptCore#newProjectEntry( + * org.eclipse.core.runtime.IPath path, + * IAccessRule[] accessRules, + * boolean combineAccessRestrictions, + * IIncludePathAttribute[] extraAttributes, + * boolean isExported) + * @see JavaScriptCore#newSourceEntry( + * org.eclipse.core.runtime.IPath path, + * org.eclipse.core.runtime.IPath[] inclusionPatterns, + * org.eclipse.core.runtime.IPath[] exclusionPatterns, + * org.eclipse.core.runtime.IPath specificOutputLocation, + * IIncludePathAttribute[] extraAttributes) + * @see JavaScriptCore#newVariableEntry( + * org.eclipse.core.runtime.IPath variablePath, + * org.eclipse.core.runtime.IPath variableSourceAttachmentPath, + * org.eclipse.core.runtime.IPath variableSourceAttachmentRootPath, + * IAccessRule[] accessRules, + * IIncludePathAttribute[] extraAttributes, + * boolean isExported) + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IIncludePathAttribute { + + /** + * Constant for the name of the jsdoc location attribute. + * + */ + String JSDOC_LOCATION_ATTRIBUTE_NAME = "javadoc_location"; //$NON-NLS-1$ + + /** + * Constant for the name of the optional attribute. The possible values + * for this attribute are"true"
or "false"
.
+ * When not present, "false"
is assumed.
+ * If the value of this attribute is "true"
, the includepath entry
+ * is optional. If the underlying resource or jar file doesn't exist, no error
+ * is reported and the includepath entry is ignored.
+ */
+ String OPTIONAL = "optional"; //$NON-NLS-1$
+
+ /**
+ * Returns the name of this includepath attribute.
+ *
+ * @return the name of this includepath attribute.
+ */
+ String getName();
+
+ /**
+ * Returns the value of this includepath attribute.
+ *
+ * @return the value of this includepath attribute.
+ */
+ String getValue();
+
+ public static final ClasspathAttribute HIDE = new ClasspathAttribute("hide","true"); //$NON-NLS-1$ //$NON-NLS-2$
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IIncludePathEntry.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IIncludePathEntry.java
new file mode 100644
index 0000000..326e4f8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IIncludePathEntry.java
@@ -0,0 +1,395 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * An entry on a JavaScript project includepath identifying one or more package fragment
+ * roots. A includepath entry has a content kind (either source,
+ * {@link IPackageFragmentRoot#K_SOURCE}, or binary, {@link IPackageFragmentRoot#K_BINARY}), which is inherited
+ * by each package fragment root and package fragment associated with the entry.
+ * + * A includepath entry can refer to any of the following:
.js
files)
+ * represent javaScript files. All javaScript files will be compiled when
+ * the project is built. The includepath entry must specify the
+ * absolute path to the root folder. Entries of this kind are
+ * associated with the {@link #CPE_SOURCE} constant.
+ * Source includepath entries can carry inclusion and exclusion patterns for
+ * selecting which source files appear as javaScript
+ * units and get compiled when the project is built.
+ * .class
files located in its output location.
+ * It will also automatically include any other libraries or projects that the required project's includepath
+ * refers to, iff the corresponding includepath entries are tagged as being exported
+ * ({@link IIncludePathEntry#isExported}).
+ * Unless exporting some includepath entries, includepaths are not chained by default -
+ * each project must specify its own includepath in its entirety.+ * Any includepath entry other than a source folder (kind {@link #CPE_SOURCE}) can + * be marked as being exported. Exported entries are automatically contributed to + * dependent projects, along with the project's default output folder, which is + * implicitly exported, and any auxiliary output folders specified on source + * includepath entries. The project's output folder(s) are always listed first, + * followed by the any exported entries. + *
+ * This interface is not intended to be implemented by clients. + * Includepath entries can be created via methods on {@link JavaScriptCore}. + *
+ * + * @see JavaScriptCore#newLibraryEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath) + * @see JavaScriptCore#newProjectEntry(org.eclipse.core.runtime.IPath) + * @see JavaScriptCore#newSourceEntry(org.eclipse.core.runtime.IPath) + * @see JavaScriptCore#newVariableEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath) + * @see JavaScriptCore#newContainerEntry(org.eclipse.core.runtime.IPath) + * @see JsGlobalScopeVariableInitializer + * @see JsGlobalScopeContainerInitializer + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IIncludePathEntry { + + /** + * Entry kind constant describing a includepath entry identifying a + * library. + */ + int CPE_LIBRARY = 1; + + /** + * Entry kind constant describing a includepath entry identifying a + * required project. + */ + int CPE_PROJECT = 2; + + /** + * Entry kind constant describing a includepath entry identifying a + * folder containing package fragments with source code + * to be validated. + */ + int CPE_SOURCE = 3; + + /** + * Entry kind constant describing a includepath entry defined using + * a path that begins with a includepath variable reference. + */ + int CPE_VARIABLE = 4; + + /** + * Entry kind constant describing a includepath entry representing + * a name includepath container. + */ + int CPE_CONTAINER = 5; + + /** + * Returns whether the access rules of the project's exported entries should be combined with this entry's access rules. + * Returns true for container entries. + * Returns false otherwise. + * + * @return whether the access rules of the project's exported entries should be combined with this entry's access rules + */ + boolean combineAccessRules(); + + /** + * Returns the possibly empty list of access rules for this entry. + * + * @return the possibly empty list of access rules for this entry + */ + IAccessRule[] getAccessRules(); + /** + * Returns the kind of files found in the package fragments identified by this + * includepath entry. + * + * @return {@link IPackageFragmentRoot#K_SOURCE} for files containing + * source code, and {@link IPackageFragmentRoot#K_BINARY} for binary + * class files. + * There is no specified value for an entry denoting a variable ({@link #CPE_VARIABLE}) + * or a includepath container ({@link #CPE_CONTAINER}). + */ + int getContentKind(); + + /** + * Returns the kind of this includepath entry. + * + * @return one of: + *+ * For source includepath entries, + * exclusion patterns allow specified portions of the resource tree rooted + * at this source entry's path to be filtered out. If no exclusion patterns + * are specified, this source entry includes all relevent files. Each path + * specified must be a relative path, and will be interpreted relative + * to this source entry's path. File patterns are case-sensitive. A file + * matched by one or more of these patterns is excluded from the + * corresponding package fragment root. + * Exclusion patterns have higher precedence than inclusion patterns; + * in other words, exclusion patterns can remove files for the ones that + * are to be included, not the other way around. + *
+ *+ * The pattern mechanism is similar to Ant's. Each pattern is represented as + * a relative path. The path segments can be regular file or folder names or simple patterns + * involving standard wildcard characters. + *
+ *
+ * '*' matches 0 or more characters within a segment. So
+ * *.js
matches .js
, a.js
+ * and Foo.js
, but not Foo.properties
+ * (does not end with .js
).
+ *
+ * '?' matches 1 character within a segment. So ?.js
+ * matches a.js
, A.js
,
+ * but not .js
or xyz.js
(neither have
+ * just one character before .js
).
+ *
+ * Combinations of *'s and ?'s are allowed. + *
+ *
+ * The special pattern '**' matches zero or more segments. In a source entry,
+ * a path like tests/
that ends in a trailing separator is interpreted
+ * as tests/**
, and would match everything under
+ * the folder named tests
.
+ *
+ * Example patterns in source entries (assuming that "js" is the only {@link JavaScriptCore#getJavaScriptLikeExtensions() JavaScript-like extension}): + *
tests/**
(or simply tests/
)
+ * matches all files under a root folder
+ * named tests
. This includes tests/Foo.js
+ * and tests/com/example/Foo.js
, but not
+ * com/example/tests/Foo.js
(not under a root folder named
+ * tests
).
+ * tests/*
matches all files directly below a root
+ * folder named tests
. This includes tests/Foo.js
+ * and tests/FooHelp.js
+ * but not tests/com/example/Foo.js
(not directly under
+ * a folder named tests
) or
+ * com/Foo.js
(not under a folder named tests
).
+ * **/tests/**
matches all files under any
+ * folder named tests
. This includes tests/Foo.js
,
+ * com/examples/tests/Foo.js
, and
+ * com/examples/tests/unit/Foo.js
, but not
+ * com/example/Foo.js
(not under a folder named
+ * tests
).
+ * null
if this kind
+ * of includepath entry does not support exclusion patterns
+ */
+ IPath[] getExclusionPatterns();
+
+ /**
+ * Returns the extra includepath attributes for this includepath entry. Returns an empty array if this entry
+ * has no extra attributes.
+ *
+ * @return the possibly empty list of extra includepath attributes for this includepath entry
+ */
+ IIncludePathAttribute[] getExtraAttributes();
+
+ /**
+ * Returns the set of patterns used to explicitly define resources
+ * to be included with this includepath entry.
+ * + * For source includepath entries, + * when no inclusion patterns are specified, the source entry includes all + * relevent files in the resource tree rooted at this source entry's path. + * Specifying one or more inclusion patterns means that only the specified + * portions of the resource tree are to be included. Each path specified + * must be a relative path, and will be interpreted relative to this source + * entry's path. File patterns are case-sensitive. A file matched by one or + * more of these patterns is included in the corresponding package fragment + * root unless it is excluded by one or more of this entrie's exclusion + * patterns. Exclusion patterns have higher precedence than inclusion + * patterns; in other words, exclusion patterns can remove files for the + * ones that are to be included, not the other way around. + *
+ *
+ * See {@link #getExclusionPatterns()} for a discussion of the syntax and
+ * semantics of path patterns. The absence of any inclusion patterns is
+ * semantically equivalent to the explicit inclusion pattern
+ * **
.
+ *
+ * Example patterns in source entries: + *
src/**
by itself includes all
+ * files under a root folder named src
.
+ * src/**
and
+ * tests/**
includes all files under the root folders
+ * named src
and tests
.
+ * src/**
together with the
+ * exclusion pattern src/**/Foo.js
includes all
+ * files under a root folder named src
except for ones
+ * named Foo.js
.
+ * null
if this kind
+ * of includepath entry does not support inclusion patterns
+ */
+ IPath[] getInclusionPatterns();
+
+ /**
+ * Returns the path of this includepath entry.
+ *
+ * The meaning of the path of a includepath entry depends on its entry kind:null
if this includepath entry has no
+ * source attachment.
+ * + * Only library and variable includepath entries may have source attachments. + * For library includepath entries, the result path (if present) locates a source + * archive or folder. This archive or folder can be located in a project of the + * workspace or outside thr workspace. For variable includepath entries, the + * result path (if present) has an analogous form and meaning as the + * variable path, namely the first segment is the name of a includepath variable. + *
+ * + * @return the path to the source archive or folder, ornull
if none
+ */
+ IPath getSourceAttachmentPath();
+
+ /**
+ * Returns the path within the source archive or folder where package fragments
+ * are located. An empty path indicates that packages are located at
+ * the root of the source archive or folder. Returns a non-null
value
+ * if and only if {@link #getSourceAttachmentPath} returns
+ * a non-null
value.
+ *
+ * @return the path within the source archive or folder, or null
if
+ * not applicable
+ */
+ IPath getSourceAttachmentRootPath();
+
+ /**
+ * Returns whether this entry is exported to dependent projects.
+ * Always returns false
for source entries (kind
+ * {@link #CPE_SOURCE}), which cannot be exported.
+ *
+ * @return true
if exported, and false
otherwise
+ */
+ boolean isExported();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IInitializer.java
new file mode 100644
index 0000000..2c27d98
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IInitializer.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * Represents a stand-alone instance or class (static) initializer in a type.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IInitializer extends IMember { + // interface used as a marker: defines no member +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJarEntryResource.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJarEntryResource.java new file mode 100644 index 0000000..512b386 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJarEntryResource.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.IPath; + +/** + * A jar entry corresponding to a non-Java resource in an archive {@link IPackageFragment} or {@link IPackageFragmentRoot}. + *+ * One can navigate the non-Java resource tree using the {@link #getChildren()} and {@link #getParent()} methods. + * Jar entry resources are either files ({@link #isFile()} returns true) or directories ({@link #isFile()} returns false). + * Files don't have any children and the returned array is always empty. + *
+ * Jar entry resources that refer to the same element are guaranteed to be equal, but not necessarily identical. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJarEntryResource extends IStorage { + + /** + * Returns the list of children of this jar entry resource. + * Returns an empty array if this jar entry is a file, or if this jar entry is a directory and it has no children. + * + * @return the children of this jar entry resource + */ + IJarEntryResource[] getChildren(); + + /** + * Returns the full, absolute path of this jar entry resource relative to the archive this jar + * entry belongs to. + *
+ * A jar entry resource's full path indicates the route from the root of the archive + * to the jar entry resource. Within an archive, there is exactly one such path + * for any given jar entry resource. The returned path never has a trailing separator. + *
+ * + * @return the absolute path of this jar entry resource + */ + IPath getFullPath(); + + /** + * Returns the parent of this jar entry resource. This is either an {@link IJarEntryResource}, an {@link IPackageFragment} + * or an {@link IPackageFragmentRoot}. + * + * @return the parent of this jar entry resource + */ + Object getParent(); + + /** + * Returns the package fragment root this jar entry file belongs to. + * + * @return the package fragment root this jar entry file belongs to. + */ + IPackageFragmentRoot getPackageFragmentRoot(); + + /** + * Returnstrue
if this jar entry represents a file.
+ * Returns false
if it is a directory.
+ *
+ * @return whether this jar entry is a file
+ */
+ boolean isFile();
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptElement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptElement.java
new file mode 100644
index 0000000..d1a6e76
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptElement.java
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.net.URI;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+
+/**
+ * Common protocol for all elements provided by the JavaScript model.
+ * JavaScript model elements are exposed to clients as handles to the actual underlying element.
+ * The JavaScript model may hand out any number of handles for each element. Handles
+ * that refer to the same element are guaranteed to be equal, but not necessarily identical.
+ *
+ * Methods annotated as "handle-only" do not require underlying elements to exist.
+ * Methods that require underlying elements to exist throw
+ * a JavaScriptModelException
when an underlying element is missing.
+ * JavaScriptModelException.isDoesNotExist
can be used to recognize
+ * this common special case.
+ *
+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJavaScriptElement extends IAdaptable, ILookupScope{ + + /** + * Constant representing a JavaScript model (workspace level object). + * A JavaScript element with this type can be safely cast to {@link IJavaScriptModel}. + */ + int JAVASCRIPT_MODEL = 1; + + /** + * Constant representing a JavaScript project. + * A JavaScript element with this type can be safely cast to {@link IJavaScriptProject}. + */ + int JAVASCRIPT_PROJECT = 2; + + /** + * Constant representing a root source folder (package fragment root). + * A JavaScript element with this type can be safely cast to {@link IPackageFragmentRoot}. + */ + int PACKAGE_FRAGMENT_ROOT = 3; + + /** + * Constant representing a source folder (package fragment). + * A JavaScript element with this type can be safely cast to {@link IPackageFragment}. + */ + int PACKAGE_FRAGMENT = 4; + + /** + * Constant representing a JavaScript file. + * A JavaScript element with this type can be safely cast to {@link IJavaScriptUnit}. + */ + int JAVASCRIPT_UNIT = 5; + + /** + * Constant representing a non-editable javaScript file. + * A JavaScript element with this type can be safely cast to {@link IClassFile}. + */ + int CLASS_FILE = 6; + + /** + * Constant representing a type (a class or interface). + * A JavaScript element with this type can be safely cast to {@link IType}. + */ + int TYPE = 7; + + /** + * Constant representing a field or a var with file scope. + * A JavaScript element with this type can be safely cast to {@link IField}. + */ + int FIELD = 8; + + /** + * Constant representing a function, method or constructor. + * A JavaScript element with this type can be safely cast to {@link IFunction}. + */ + int METHOD = 9; + + /** + * Constant representing a stand-alone instance or class initializer. + * A JavaScript element with this type can be safely cast to {@link IInitializer}. + */ + int INITIALIZER = 10; + + /** + * Constant representing all import declarations within a compilation unit. + * A JavaScript element with this type can be safely cast to {@link IImportContainer}. + * + * This type only applies to ECMAScript 4 which is not yet supported + */ + int IMPORT_CONTAINER = 12; + + /** + * Constant representing an import declaration within a compilation unit. + * A JavaScript element with this type can be safely cast to {@link IImportDeclaration}. + * + * This type only applies to ECMAScript 4 which is not yet supported + */ + int IMPORT_DECLARATION = 13; + + /** + * Constant representing a local variable declaration. + * A JavaScript element with this type can be safely cast to {@link ILocalVariable}. + */ + int LOCAL_VARIABLE = 14; + + /** + * Returns whether this JavaScript element exists in the model. + *
+ * JavaScript elements are handle objects that may or may not be backed by an
+ * actual element. JavaScript elements that are backed by an actual element are
+ * said to "exist", and this method returns true
. For JavaScript
+ * elements that are not working copies, it is always the case that if the
+ * element exists, then its parent also exists (provided it has one) and
+ * includes the element as one of its children. It is therefore possible
+ * to navigated to any existing JavaScript element from the root of the JavaScript model
+ * along a chain of existing JavaScript elements. On the other hand, working
+ * copies are said to exist until they are destroyed (with
+ * IWorkingCopy.destroy
). Unlike regular JavaScript elements, a
+ * working copy never shows up among the children of its parent element
+ * (which may or may not exist).
+ *
true
if this element exists in the JavaScript model, and
+ * false
if this element does not exist
+ */
+ boolean exists();
+
+ /**
+ * Returns the first ancestor of this JavaScript element that has the given type.
+ * Returns null
if no such an ancestor can be found.
+ * This is a handle-only method.
+ *
+ * @param ancestorType the given type
+ * @return the first ancestor of this JavaScript element that has the given type, null if no such an ancestor can be found
+ */
+ IJavaScriptElement getAncestor(int ancestorType);
+
+ /**
+ * Returns the Jsdoc as an html source if this element has an attached jsdoc, + * null otherwise.
+ *This should be used only for binary elements. Source elements will always return null.
+ *The encoding used to read the jsdoc is the one defined by the content type of the + * file. If none is defined, then the project's encoding of this java element is used. If the project's + * encoding cannot be retrieved, then the platform encoding is used.
+ *In case of the jsdoc doesn't exist for this element, null is returned.
+ * + *The html is extracted from the attached jsdoc and provided as is. No + * transformation or validation is done.
+ * + * @param monitor the given progress monitor + * @exception JavaScriptModelException if:null
if there is no resource that corresponds to
+ * this element.
+ *
+ * For example, the corresponding resource for an IJavaScriptUnit
+ * is its underlying IFile
. The corresponding resource for
+ * an IPackageFragment
that is not contained in an archive
+ * is its underlying IFolder
. An IPackageFragment
+ * contained in an archive has no corresponding resource. Similarly, there
+ * are no corresponding resources for IMethods
,
+ * IFields
, etc.
+ *
+ *
+ * @return the corresponding resource, or null
if none
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ IResource getCorrespondingResource() throws JavaScriptModelException;
+
+ /**
+ * Returns the name of this element. This is a handle-only method.
+ *
+ * @return the element name
+ */
+ String getElementName();
+
+ /**
+ * Returns this element's kind encoded as an integer.
+ * This is a handle-only method.
+ *
+ * @return the kind of element; one of the constants declared in
+ * IJavaScriptElement
+ * @see IJavaScriptElement
+ */
+ int getElementType();
+
+ /**
+ * Returns a string representation of this element handle. The format of
+ * the string is not specified; however, the identifier is stable across
+ * workspace sessions, and can be used to recreate this handle via the
+ * JavaScriptCore.create(String)
method.
+ *
+ * @return the string handle identifier
+ * @see JavaScriptCore#create(java.lang.String)
+ */
+ String getHandleIdentifier();
+
+ /**
+ * Returns the JavaScript model.
+ * This is a handle-only method.
+ *
+ * @return the JavaScript model
+ */
+ IJavaScriptModel getJavaScriptModel();
+
+ /**
+ * Returns the JavaScript project this element is contained in,
+ * or null
if this element is not contained in any JavaScript project
+ * (for instance, the IJavaScriptModel
is not contained in any JavaScript
+ * project).
+ * This is a handle-only method.
+ *
+ * @return the containing JavaScript project, or null
if this element is
+ * not contained in a JavaScript project
+ */
+ IJavaScriptProject getJavaScriptProject();
+
+ /**
+ * Returns the first openable parent. If this element is openable, the element
+ * itself is returned. Returns null
if this element doesn't have
+ * an openable parent.
+ * This is a handle-only method.
+ *
+ * @return the first openable parent or null
if this element doesn't have
+ * an openable parent.
+ */
+ IOpenable getOpenable();
+
+ /**
+ * Returns the element directly containing this element,
+ * or null
if this element has no parent.
+ * This is a handle-only method.
+ *
+ * @return the parent element, or null
if this element has no parent
+ */
+ IJavaScriptElement getParent();
+
+ /**
+ * Returns the path to the innermost resource enclosing this element.
+ * If this element is not included in an external archive,
+ * the path returned is the full, absolute path to the underlying resource,
+ * relative to the workbench.
+ * If this element is included in an external archive,
+ * the path returned is the absolute path to the archive in the file system.
+ * This is a handle-only method.
+ *
+ * @return the path to the innermost resource enclosing this element
+ */
+ IPath getPath();
+
+ /**
+ * Returns the primary element (whose compilation unit is the primary compilation unit)
+ * this working copy element was created from, or this element if it is a descendant of a
+ * primary javaScript unit or if it is not a descendant of a working copy (e.g. it is a
+ * binary member).
+ * The returned element may or may not exist.
+ *
+ * @return the primary element this working copy element was created from, or this
+ * element.
+ */
+ IJavaScriptElement getPrimaryElement();
+
+ /**
+ * Returns the innermost resource enclosing this element.
+ * If this element is included in an archive and this archive is not external,
+ * this is the underlying resource corresponding to the archive.
+ * If this element is included in an external archive, null
+ * is returned.
+ * This is a handle-only method.
+ *
+ * @return the innermost resource enclosing this element, null
if this
+ * element is included in an external archive
+ */
+ IResource getResource();
+
+ /**
+ * Returns the scheduling rule associated with this JavaScript element.
+ * This is a handle-only method.
+ *
+ * @return the scheduling rule associated with this JavaScript element
+ */
+ ISchedulingRule getSchedulingRule();
+
+ /**
+ * Returns the smallest underlying resource that contains
+ * this element, or null
if this element is not contained
+ * in a resource.
+ *
+ * @return the underlying resource, or null
if none
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its underlying resource
+ */
+ IResource getUnderlyingResource() throws JavaScriptModelException;
+
+ /**
+ * Returns whether this JavaScript element is read-only. An element is read-only
+ * if its structure cannot be modified by the java model.
+ *
+ * Note this is different from IResource.isReadOnly(). For example, .jar + * files are read-only as the javaScript model doesn't know how to add/remove + * elements in this file, but the underlying IFile can be writable. + *
+ * This is a handle-only method.
+ *
+ * @return true
if this element is read-only
+ */
+ boolean isReadOnly();
+
+ /**
+ * Returns whether the structure of this element is known. For example, for a
+ * javaScript file that could not be parsed, false
is returned.
+ * If the structure of an element is unknown, navigations will return reasonable
+ * defaults. For example, getChildren
will return an empty collection.
+ *
+ * Note: This does not imply anything about consistency with the + * underlying resource/buffer contents. + *
+ * + * @returntrue
if the structure of this element is known
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ boolean isStructureKnown() throws JavaScriptModelException;
+ /**
+ * Returns a readable (non mangled) name. In virtual elements this is derived from a JsGlobalScopeContainerInitializer
+ *
+ * @return a human friendly element name.
+ */
+ String getDisplayName();
+ /**
+ * Returns if this is a virtual element (ie actually exists in the model or filesystem).
+ *
+ * @return if this is a virtual element.
+ */
+ boolean isVirtual();
+
+ /**
+ * If a resource is virtual, then return a real host path for the element. (Query the container initializer).
+ *
+ * @return if this is a virtual element.
+ */
+ URI getHostPath();
+
+ /**
+ * Returns the Super type this file is considered to be a member of. For Browser base javaScript, this would be "Window".
+ *
+ * @return the supertype for the javascript file.
+ */
+ LibrarySuperType getCommonSuperType();
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptElementDelta.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptElementDelta.java
new file mode 100644
index 0000000..28193cb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptElementDelta.java
@@ -0,0 +1,375 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+
+/**
+ * A JavaScript element delta describes changes in JavaScript element between two discrete
+ * points in time. Given a delta, clients can access the element that has
+ * changed, and any children that have changed.
+ * + * Deltas have a different status depending on the kind of change they represent. + * The list below summarizes each status (as returned by {@link #getKind}) + * and its meaning (see individual constants for a more detailled description): + *
+ * Move operations are indicated by other change flags, layered on top + * of the change flags described above. If element A is moved to become B, + * the delta for the change in A will have status {@link #REMOVED}, + * with change flag {@link #F_MOVED_TO}. In this case, + * {@link #getMovedToElement} on delta A will return the handle for B. + * The delta for B will have status {@link #ADDED}, with change flag + * {@link #F_MOVED_FROM}, and {@link #getMovedFromElement} on delta + * B will return the handle for A. (Note, the handle to A in this case represents + * an element that no longer exists). + *
+ *+ * Note that the move change flags only describe the changes to a single element, they + * do not imply anything about the parent or children of the element. + *
+ *+ * The {@link #F_ADDED_TO_CLASSPATH}, {@link #F_REMOVED_FROM_CLASSPATH} and + * {@link #F_INCLUDEPATH_REORDER} flags are triggered by changes to a project's includepath. They do not mean that + * the underlying resource was added, removed or changed. For example, if a project P already contains a folder src, then + * adding a includepath entry with the 'P/src' path to the project's includepath will result in an {@link IJavaScriptElementDelta} + * with the {@link #F_ADDED_TO_CLASSPATH} flag for the {@link IPackageFragmentRoot} P/src. + * On the contrary, if a resource is physically added, removed or changed and this resource corresponds to a includepath + * entry of the project, then an {@link IJavaScriptElementDelta} with the {@link #ADDED}, + * {@link #REMOVED}, or {@link #CHANGED} kind will be fired. + *
+ *+ * Note that when a source attachment path or a source attachment root path is changed, then the flags of the delta contain + * both {@link #F_SOURCEATTACHED} and {@link #F_SOURCEDETACHED}. + *
+ *+ * No assumptions should be made on whether the javaScript element delta tree is rooted at the {@link IJavaScriptModel} + * level or not. + *
+ *+ * {@link IJavaScriptElementDelta} object are not valid outside the dynamic scope + * of the notification. + *
+ *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJavaScriptElementDelta { + + /** + * Status constant indicating that the element has been added. + * Note that an added javaScript element delta has no children, as they are all implicitely added. + */ + public int ADDED = 1; + + /** + * Status constant indicating that the element has been removed. + * Note that a removed javaScript element delta has no children, as they are all implicitely removed. + */ + public int REMOVED = 2; + + /** + * Status constant indicating that the element has been changed, + * as described by the change flags. + * + * @see #getFlags() + */ + public int CHANGED = 4; + + /** + * Change flag indicating that the content of the element has changed. + * This flag is only valid for elements which correspond to files. + */ + public int F_CONTENT = 0x000001; + + /** + * Change flag indicating that the modifiers of the element have changed. + * This flag is only valid if the element is an {@link IMember}. + */ + public int F_MODIFIERS = 0x000002; + + /** + * Change flag indicating that there are changes to the children of the element. + * This flag is only valid if the element is an {@link IParent}. + */ + public int F_CHILDREN = 0x000008; + + /** + * Change flag indicating that the element was moved from another location. + * The location of the old element can be retrieved using {@link #getMovedFromElement}. + */ + public int F_MOVED_FROM = 0x000010; + + /** + * Change flag indicating that the element was moved to another location. + * The location of the new element can be retrieved using {@link #getMovedToElement}. + */ + public int F_MOVED_TO = 0x000020; + + /** + * Change flag indicating that a includepath entry corresponding to the element has been added to the project's includepath. + * This flag is only valid if the element is an {@link IPackageFragmentRoot}. + */ + public int F_ADDED_TO_CLASSPATH = 0x000040; + + /** + * Change flag indicating that a includepath entry corresponding to the element has been removed from the project's + * includepath. This flag is only valid if the element is an {@link IPackageFragmentRoot}. + */ + public int F_REMOVED_FROM_CLASSPATH = 0x000080; + + /** + * Change flag indicating that the element has changed position relatively to its siblings. + * If the element is an {@link IPackageFragmentRoot}, a includepath entry corresponding + * to the element has changed position in the project's includepath. + * + */ + public int F_REORDER = 0x000100; + + /** + * Change flag indicating that the underlying {@link org.eclipse.core.resources.IProject} has been + * opened. This flag is only valid if the element is an {@link IJavaScriptProject}. + */ + public int F_OPENED = 0x000200; + + /** + * Change flag indicating that the underlying {@link org.eclipse.core.resources.IProject} has been + * closed. This flag is only valid if the element is an {@link IJavaScriptProject}. + */ + public int F_CLOSED = 0x000400; + + /** + * Change flag indicating that one of the supertypes of an {@link IType} + * has changed. + */ + public int F_SUPER_TYPES = 0x000800; + + /** + * Change flag indicating that the source attachment path or the source attachment root path of a includepath entry + * corresponding to the element was added. This flag is only valid if the element is an + * {@link IPackageFragmentRoot}. + */ + public int F_SOURCEATTACHED = 0x001000; + + /** + * Change flag indicating that the source attachment path or the source attachment root path of a includepath entry + * corresponding to the element was removed. This flag is only valid if the element is an + * {@link IPackageFragmentRoot}. + */ + public int F_SOURCEDETACHED = 0x002000; + + /** + * Change flag indicating that this is a fine-grained delta, that is, an analysis down + * to the members level was done to determine if there were structural changes to + * members. + *+ * Clients can use this flag to find out if a javaScript unit + * that have a {@link #F_CONTENT} change should assume that there are + * no finer grained changes ({@link #F_FINE_GRAINED} is set) or if + * finer grained changes were not considered ({@link #F_FINE_GRAINED} + * is not set). + * + */ + public int F_FINE_GRAINED = 0x004000; + + /** + * Change flag indicating that the element's archive content on the includepath has changed. + * This flag is only valid if the element is an {@link IPackageFragmentRoot} + * which is an archive. + * + * @see IPackageFragmentRoot#isArchive() + */ + public int F_ARCHIVE_CONTENT_CHANGED = 0x008000; + + /** + * Change flag indicating that a javaScript unit has become a primary working copy, or that a + * primary working copy has reverted to a javaScript unit. + * This flag is only valid if the element is an {@link IJavaScriptUnit}. + * + */ + public int F_PRIMARY_WORKING_COPY = 0x010000; + + /** + * Change flag indicating that the raw includepath (or the output folder) of a project has changed. + * This flag is only valid if the element is an {@link IJavaScriptProject}. + * + */ + public int F_INCLUDEPATH_CHANGED = 0x020000; + + /** + * Change flag indicating that the resource of a primary javaScript unit has changed. + * This flag is only valid if the element is a primary {@link IJavaScriptUnit}. + * + */ + public int F_PRIMARY_RESOURCE = 0x040000; + + /** + * Change flag indicating that a reconcile operation has affected the javaScript unit AST created in a + * previous reconcile operation. Use {@link #getJavaScriptUnitAST()} to retrieve the AST (if any is available). + * This flag is only valid if the element is an {@link IJavaScriptUnit} in working copy mode. + * + */ + public int F_AST_AFFECTED = 0x080000; + + /** + * Change flag indicating that the categories of the element have changed. + * This flag is only valid if the element is an {@link IMember}. + * + */ + public int F_CATEGORIES = 0x100000; + + /** + * Returns deltas for the children that have been added. + * @return deltas for the children that have been added + */ + public IJavaScriptElementDelta[] getAddedChildren(); + + /** + * Returns deltas for the affected (added, removed, or changed) children. + * @return deltas for the affected (added, removed, or changed) children + */ + public IJavaScriptElementDelta[] getAffectedChildren(); + + /** + * Returns the javaScript unit AST created by the last reconcile operation on this delta's element. + * This returns a non-null value if and only if: + *
&
operand. For example:
+ * + * if ((delta.getFlags() & IJavaScriptElementDelta.F_CONTENT) != 0) { + * // the delta indicates a content change + * } + *+ * + * @return flags that describe how an element has changed + */ + public int getFlags(); + + /** + * Returns the kind of this delta - one of {@link #ADDED}, {@link #REMOVED}, + * or {@link #CHANGED}. + * + * @return the kind of this delta + */ + public int getKind(); + + /** + * Returns an element describing this element before it was moved + * to its current location, or
null
if the
+ * {@link #F_MOVED_FROM} change flag is not set.
+ *
+ * @return an element describing this element before it was moved
+ * to its current location, or null
if the
+ * {@link #F_MOVED_FROM} change flag is not set
+ */
+ public IJavaScriptElement getMovedFromElement();
+
+ /**
+ * Returns an element describing this element in its new location,
+ * or null
if the {@link #F_MOVED_TO} change
+ * flag is not set.
+ *
+ * @return an element describing this element in its new location,
+ * or null
if the {@link #F_MOVED_TO} change
+ * flag is not set
+ */
+ public IJavaScriptElement getMovedToElement();
+
+ /**
+ * Returns deltas for the children which have been removed.
+ *
+ * @return deltas for the children which have been removed
+ */
+ public IJavaScriptElementDelta[] getRemovedChildren();
+
+ /**
+ * Returns the collection of resource deltas.
+ * + * Note that resource deltas, like JavaScript element deltas, are generally only valid + * for the dynamic scope of an event notification. Clients must not hang on to + * these objects. + *
+ * + * @return the underlying resource deltas, ornull
if none
+ */
+ public IResourceDelta[] getResourceDeltas();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModel.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModel.java
new file mode 100644
index 0000000..0b75e73
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModel.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Represent the root JavaScript element corresponding to the workspace.
+ * Since there is only one such root element, it is commonly referred to as
+ * the JavaScript model element.
+ * The JavaScript model element needs to be opened before it can be navigated or manipulated.
+ * The JavaScript model element has no parent (it is the root of the JavaScript element
+ * hierarchy). Its children are IJavaScriptProject
s.
+ * + * This interface provides methods for performing copy, move, rename, and + * delete operations on multiple JavaScript elements. + *
+ *
+ * This interface is not intended to be implemented by clients. An instance
+ * of one of these handles can be created via
+ * JavaScriptCore.create(workspace.getRoot())
.
+ *
IJavaScriptElement
whose
+ * resource is the given resource or a non-JavaScript resource which is the given resource.
+ *
+ * Note: no existency check is performed on the argument resource. If it is not accessible
+ * (see IResource.isAccessible()
) yet but would be located in JavaScript model
+ * range, then it will return true
.
+ *
+ * If the resource is accessible, it can be reached by navigating the JavaScript model down using the
+ * getChildren()
and/or getNonJavaResources()
methods.
+ *
+ * Optionally, each copy can positioned before a sibling
+ * element. If null
is specified for a given sibling, the copy
+ * is inserted as the last child of its associated container.
+ *
+ * Optionally, each copy can be renamed. If
+ * null
is specified for the new name, the copy
+ * is not renamed.
+ *
+ * Optionally, any existing child in the destination container with
+ * the same name can be replaced by specifying true
for
+ * force. Otherwise an exception is thrown in the event that a name
+ * collision occurs.
+ *
null
; or null
+ * @param renamings the list of new names any of which may be
+ * null
; or null
+ * @param replace true
if any existing child in a target container
+ * with the target name should be replaced, and false
to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if an element could not be copied. Reasons include:
+ * CoreException
occurred while updating an underlying resourceINVALID_DESTINATION
)INVALID_SIBLING
)INVALID_NAME
)replace
has been specified as false
(NAME_COLLISION
)READ_ONLY
) CoreException
occurred while updating an underlying resourceREAD_ONLY
) + * Non-JavaScript projects include all projects that are closed (even if they have the + * JavaScript nature). + *
+ * + * @return an array of non-JavaScript projects (IProject
s) contained
+ * in the workspace.
+ * @throws JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+Object[] getNonJavaScriptResources() throws JavaScriptModelException;
+/**
+ * Returns the workspace associated with this JavaScript model.
+ *
+ * @return the workspace associated with this JavaScript model
+ */
+IWorkspace getWorkspace();
+/**
+ * Moves the given elements to the specified container(s).
+ * If one container is specified, all elements are moved to that
+ * container. If more than one container is specified, the number of
+ * elements and containers must match, and each element is moved to
+ * its associated container.
+ *
+ * Optionally, each element can positioned before a sibling
+ * element. If null
is specified for sibling, the element
+ * is inserted as the last child of its associated container.
+ *
+ * Optionally, each element can be renamed. If
+ * null
is specified for the new name, the element
+ * is not renamed.
+ *
+ * Optionally, any existing child in the destination container with
+ * the same name can be replaced by specifying true
for
+ * force. Otherwise an exception is thrown in the event that a name
+ * collision occurs.
+ *
null
; or null
+ * @param renamings the list of new names any of which may be
+ * null
; or null
+ * @param replace true
if any existing child in a target container
+ * with the target name should be replaced, and false
to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if an element could not be moved. Reasons include:
+ * CoreException
occurred while updating an underlying resourceINVALID_DESTINATION
)INVALID_SIBLING
)INVALID_NAME
)replace
has been specified as false
(NAME_COLLISION
)READ_ONLY
) null
+ */
+void move(IJavaScriptElement[] elements, IJavaScriptElement[] containers, IJavaScriptElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws JavaScriptModelException;
+
+/**
+ * Triggers an update of the JavaScriptModel with respect to the referenced external archives.
+ * This operation will issue a JavaScriptModel delta describing the discovered changes, in term
+ * of JavaScript element package fragment roots added, removed or changed.
+ * Note that a collection of elements can be passed so as to narrow the set of archives
+ * to refresh (passing null
along is equivalent to refreshing the entire mode).
+ * The elements can be:
+ * In case an archive is used by multiple projects, the delta issued will account for + * all of them. This means that even if a project was not part of the elements scope, it + * may still be notified of changes if it is referencing a library comprised in the scope. + *
+ * @param elementsScope - a collection of elements defining the scope of the refresh + * @param monitor - a progress monitor used to report progress + * @exception JavaScriptModelException in one of the corresponding situation: + *
true
if an existing child in a target container
+ * with the target name should be replaced, and false
to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if an element could not be renamed. Reasons include:
+ * CoreException
occurred while updating an underlying resource
+ * INVALID_NAME
)
+ * replace
has been specified as false
(NAME_COLLISION
)
+ * READ_ONLY
)
+ * + * This interface declares constants only; it is not intended to be implemented + * or extended. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJavaScriptModelMarker { + + /** + * JavaScript model problem marker type (value + *"org.eclipse.wst.jsdt.core.problem"
). This can be used to
+ * recognize those markers in the workspace that flag problems detected by
+ * the JavaScript tooling during validation.
+ */
+ String JAVASCRIPT_MODEL_PROBLEM_MARKER = JavaScriptCore.PLUGIN_ID + ".problem"; //$NON-NLS-1$
+
+ /**
+ * JavaScript model transient problem marker type (value
+ * "org.eclipse.wst.jsdt.core.transient_problem"
). This can be
+ * used to recognize those markers in the workspace that flag transient
+ * problems detected by the JavaScript tooling (such as a problem detected by the
+ * outliner, or a problem detected during a code completion). Since 1.0,
+ * transient problems are reported as IProblem
through
+ * various API. Only the evaluation API is still producing markers for
+ * transient problems.
+ *
+ * @see org.eclipse.wst.jsdt.core.compiler.IProblem
+ * @see org.eclipse.wst.jsdt.core.eval.ICodeSnippetRequestor#acceptProblem(org.eclipse.core.resources.IMarker,String,
+ * int)
+ */
+ String TRANSIENT_PROBLEM = JavaScriptCore.PLUGIN_ID + ".transient_problem"; //$NON-NLS-1$
+
+ /**
+ * JavaScript model task marker type (value
+ * "org.eclipse.wst.jsdt.core.task"
). This can be used to
+ * recognize task markers in the workspace that correspond to tasks
+ * specified in JavaScript source comments and detected during compilation (for
+ * example, 'TO-DO: ...'). Tasks are identified by a task tag, which can be
+ * customized through JavaScriptCore
option
+ * "org.eclipse.wst.jsdt.core.compiler.taskTag"
.
+ *
+ */
+ String TASK_MARKER = JavaScriptCore.PLUGIN_ID + ".task"; //$NON-NLS-1$
+
+ /**
+ * Id marker attribute (value "arguments"
). Arguments are
+ * concatenated into one String, prefixed with an argument count (followed
+ * with colon separator) and separated with '#' characters. For example: {
+ * "foo", "bar" } is encoded as "2:foo#bar", { } is encoded as "0: "
+ *
+ */
+ String ARGUMENTS = "arguments"; //$NON-NLS-1$
+
+ /**
+ * ID marker attribute (value "id"
).
+ */
+ String ID = "id"; //$NON-NLS-1$
+
+ /**
+ * ID category marker attribute (value "categoryId"
)
+ */
+ String CATEGORY_ID = "categoryId"; //$NON-NLS-1$
+
+ /**
+ * Flags marker attribute (value "flags"
). Reserved for
+ * future use.
+ */
+ String FLAGS = "flags"; //$NON-NLS-1$
+
+ /**
+ * Cycle detected marker attribute (value "cycleDetected"
).
+ * Used only on buildpath problem markers. The value of this attribute is
+ * either "true" or "false".
+ */
+ String CYCLE_DETECTED = "cycleDetected"; //$NON-NLS-1$
+
+ /**
+ * Include path problem marker type (value
+ * "org.eclipse.wst.jsdt.core.buildpath_problem"
). This can be
+ * used to recognize those markers in the workspace that flag problems
+ * detected by the JavaScript tooling during includepath setting.
+ */
+ String BUILDPATH_PROBLEM_MARKER = JavaScriptCore.PLUGIN_ID
+ + ".buildpath_problem"; //$NON-NLS-1$
+
+ /**
+ * IncludePath file format marker attribute (value
+ * "classpathFileFormat"
). Used only on includepath problem
+ * markers. The value of this attribute is either "true" or "false".
+ *
+ */
+ String INCLUDEPATH_FILE_FORMAT = "classpathFileFormat"; //$NON-NLS-1$
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModelStatus.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModelStatus.java
new file mode 100644
index 0000000..49d7e7c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModelStatus.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Represents the outcome of an JavaScript model operation. Status objects are
+ * used inside JavaScriptModelException
objects to indicate what went
+ * wrong.
+ *
+ * JavaScript model status object are distinguished by their plug-in id:
+ * getPlugin
returns "org.eclipse.wst.jsdt.core"
.
+ * getCode
returns one of the status codes declared in
+ * IJavaScriptModelStatusConstants
.
+ *
+ * A JavaScript model status may also carry additional information (that is, in
+ * addition to the information defined in IStatus
):
+ *
+ * This interface is not intended to be implemented by clients. + *
+ * + * @see org.eclipse.core.runtime.IStatus + * @see IJavaScriptModelStatusConstants + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJavaScriptModelStatus extends IStatus { +/** + * Returns any JavaScript elements associated with the failure (see specification + * of the status code), or an empty array if no elements are related to this + * particular status code. + * + * @return the list of JavaScript element culprits + * @see IJavaScriptModelStatusConstants + */ +IJavaScriptElement[] getElements(); +/** + * Returns the path associated with the failure (see specification + * of the status code), ornull
if the failure is not
+ * one of DEVICE_PATH
, INVALID_PATH
,
+ * PATH_OUTSIDE_PROJECT
, or RELATIVE_PATH
.
+ *
+ * @return the path that caused the failure, or null
if none
+ * @see IJavaScriptModelStatusConstants#DEVICE_PATH
+ * @see IJavaScriptModelStatusConstants#INVALID_PATH
+ * @see IJavaScriptModelStatusConstants#PATH_OUTSIDE_PROJECT
+ * @see IJavaScriptModelStatusConstants#RELATIVE_PATH
+ */
+IPath getPath();
+/**
+ * Returns whether this status indicates that a JavaScript model element does not exist.
+ * This convenience method is equivalent to
+ * getCode() == IJavaScriptModelStatusConstants.ELEMENT_DOES_NOT_EXIST
.
+ *
+ * @return true
if the status code indicates that a JavaScript model
+ * element does not exist
+ * @see IJavaScriptModelStatusConstants#ELEMENT_DOES_NOT_EXIST
+ */
+boolean isDoesNotExist();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModelStatusConstants.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModelStatusConstants.java
new file mode 100644
index 0000000..39e76ac
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptModelStatusConstants.java
@@ -0,0 +1,319 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ * TODO missing 2.1 and subsequent contributions
+ * VALIDATION_FAILURE
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * Status codes used with JavaScript model status objects.
+ * + * This interface declares constants only; it is not intended to be implemented + * or extended. + *
+ * + * @see IJavaScriptModelStatus + * @see org.eclipse.core.runtime.IStatus#getCode() + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJavaScriptModelStatusConstants { + + /** + * Status constant indicating that a container path was resolved + * to invalid entries (null or container). + */ + public static final int INVALID_CP_CONTAINER_ENTRY = 962; + + /** + * Status constant indicating that a container path was not resolvable + * indicating either the referred container is undefined, unbound. + */ + public static final int CP_CONTAINER_PATH_UNBOUND = 963; + + /** + * Status constant indicating that a includepath entry was invalid + */ + public static final int INVALID_INCLUDEPATH = 964; + + /** + * Status constant indicating that a variable path was not resolvable + * indicating either the referred variable is undefined, unbound or the resolved + * variable path does not correspond to an existing file or folder. + */ + public static final int CP_VARIABLE_PATH_UNBOUND = 965; + + /** + * Status constant indicating a core exception occurred. + * UsegetException
to retrieve a CoreException
.
+ */
+ public static final int CORE_EXCEPTION = 966;
+
+ /**
+ * Status constant indicating one or more of the elements
+ * supplied are not of a valid type for the operation to
+ * process.
+ * The element(s) can be retrieved using getElements
on the status object.
+ */
+ public static final int INVALID_ELEMENT_TYPES = 967;
+
+ /**
+ * Status constant indicating that no elements were
+ * provided to the operation for processing.
+ */
+ public static final int NO_ELEMENTS_TO_PROCESS = 968;
+
+ /**
+ * Status constant indicating that one or more elements
+ * supplied do not exist.
+ * The element(s) can be retrieved using getElements
on the status object.
+ *
+ * @see IJavaScriptModelStatus#isDoesNotExist()
+ */
+ public static final int ELEMENT_DOES_NOT_EXIST = 969;
+
+ /**
+ * Status constant indicating that a null
path was
+ * supplied to the operation.
+ */
+ public static final int NULL_PATH = 970;
+
+ /**
+ * Status constant indicating that a path outside of the
+ * project was supplied to the operation. The path can be retrieved using
+ * getPath
on the status object.
+ */
+ public static final int PATH_OUTSIDE_PROJECT = 971;
+
+ /**
+ * Status constant indicating that a relative path
+ * was supplied to the operation when an absolute path is
+ * required. The path can be retrieved using getPath
on the
+ * status object.
+ */
+ public static final int RELATIVE_PATH = 972;
+
+ /**
+ * Status constant indicating that a path specifying a device
+ * was supplied to the operation when a path with no device is
+ * required. The path can be retrieved using getPath
on the
+ * status object.
+ */
+ public static final int DEVICE_PATH = 973;
+
+ /**
+ * Status constant indicating that a string
+ * was supplied to the operation that was null
.
+ */
+ public static final int NULL_STRING = 974;
+
+ /**
+ * Status constant indicating that the operation encountered
+ * a read-only element.
+ * The element(s) can be retrieved using getElements
on the status object.
+ */
+ public static final int READ_ONLY = 976;
+
+ /**
+ * Status constant indicating that a naming collision would occur
+ * if the operation proceeded.
+ */
+ public static final int NAME_COLLISION = 977;
+
+ /**
+ * Status constant indicating that a destination provided for a copy/move/rename operation
+ * is invalid.
+ * The destination element can be retrieved using getElements
on the status object.
+ */
+ public static final int INVALID_DESTINATION = 978;
+
+ /**
+ * Status constant indicating that a path provided to an operation
+ * is invalid. The path can be retrieved using getPath
on the
+ * status object.
+ */
+ public static final int INVALID_PATH = 979;
+
+ /**
+ * Status constant indicating the given source position is out of bounds.
+ */
+ public static final int INDEX_OUT_OF_BOUNDS = 980;
+
+ /**
+ * Status constant indicating there is an update conflict
+ * for a working copy. The compilation unit on which the
+ * working copy is based has changed since the working copy
+ * was created.
+ */
+ public static final int UPDATE_CONFLICT = 981;
+
+ /**
+ * Status constant indicating that null
was specified
+ * as a name argument.
+ */
+ public static final int NULL_NAME = 982;
+
+ /**
+ * Status constant indicating that a name provided is not syntactically correct.
+ * The name can be retrieved from getString
.
+ */
+ public static final int INVALID_NAME = 983;
+
+ /**
+ * Status constant indicating that the specified contents
+ * are not valid.
+ */
+ public static final int INVALID_CONTENTS = 984;
+
+ /**
+ * Status constant indicating that an java.io.IOException
+ * occurred.
+ */
+ public static final int IO_EXCEPTION = 985;
+
+ /**
+ * Status constant indicating that a DOMException
+ * occurred.
+ */
+ public static final int DOM_EXCEPTION = 986;
+
+ /**
+ * Status constant indicating that a TargetException
+ * occurred.
+ */
+ public static final int TARGET_EXCEPTION = 987;
+
+ /**
+ * Status constant indicating that the JavaScript validator
+ * could not be initialized.
+ */
+ public static final int BUILDER_INITIALIZATION_ERROR = 990;
+
+ /**
+ * Status constant indicating that the JavaScript validator's last built state
+ * could not be serialized or deserialized.
+ */
+ public static final int BUILDER_SERIALIZATION_ERROR = 991;
+
+ /**
+ * Status constant indicating that an error was encountered while
+ * trying to evaluate a code snippet, or other item.
+ */
+ public static final int EVALUATION_ERROR = 992;
+
+ /**
+ * Status constant indicating that a sibling specified is not valid.
+ */
+ public static final int INVALID_SIBLING = 993;
+
+ /**
+ * Status indicating that a JavaScript element could not be created because
+ * the underlying resource is invalid.
+ * @see JavaScriptCore
+ */
+ public static final int INVALID_RESOURCE = 995;
+
+ /**
+ * Status indicating that a JavaScript element could not be created because
+ * the underlying resource is not of an appropriate type.
+ * @see JavaScriptCore
+ */
+ public static final int INVALID_RESOURCE_TYPE = 996;
+
+ /**
+ * Status indicating that a JavaScript element could not be created because
+ * the project owning underlying resource does not have the JavaScript nature.
+ * @see JavaScriptCore
+ */
+ public static final int INVALID_PROJECT = 997;
+
+ /**
+ * Status indicating that the package declaration in a IJavaScriptUnit
+ * does not correspond to the IPackageFragment
it belongs to.
+ * The getString
method of the associated status object
+ * gives the name of the package in which the IJavaScriptUnit
is
+ * declared.
+ */
+ public static final int INVALID_PACKAGE = 998;
+
+ /**
+ * Status indicating that the corresponding resource has no local contents yet.
+ * This might happen when attempting to use a resource before its contents
+ * has been made locally available.
+ */
+ public static final int NO_LOCAL_CONTENTS = 999;
+
+ /**
+ * Status indicating that a .jsdtScope file is ill-formed, and thus cannot
+ * be read/written successfully.
+ */
+ public static final int INVALID_INCLUDEPATH_FILE_FORMAT = 1000;
+
+ /**
+ * Status indicating that a project is involved in a build path cycle.
+ */
+ public static final int INCLUDEPATH_CYCLE = 1001;
+
+ /**
+ * Status constant indicating that an inclusion or an exclusion pattern got specified
+ * on a includepath source entry, though it was explicitely disabled
+ * according to its project preference settings.
+ * @see org.eclipse.wst.jsdt.core.IJavaScriptProject#getOptions(boolean)
+ */
+ public static final int DISABLED_CP_EXCLUSION_PATTERNS = 1002;
+
+ /**
+ * Status constant indicating that a specific output location got associated
+ * with a source entry, though it was explicitely disabled according to its project
+ * preference settings.
+ * @see org.eclipse.wst.jsdt.core.IJavaScriptProject#getOptions(boolean)
+ */
+ public static final int DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS = 1003;
+
+ /*
+ * Status constant indicating that a project is prerequisiting some library for which the
+ * classfile JDK version level is more recent than the project JDK target level setting.
+ * This can indicate some binary incompatibility issues later on.
+ */
+ public static final int INCOMPATIBLE_JDK_LEVEL = 1004;
+
+ /**
+ * Status constant indicating that a validation failure occurred.
+ */
+ public static final int VALIDATION_FAILURE = 1005;
+ /**
+ * Status constant indicating that an element is not on its project's includepath.
+ */
+ public static final int ELEMENT_NOT_ON_CLASSPATH = 1006;
+ /*
+ * Status constant indicating that a compiler option is invalid.
+ */
+// public static final int INVALID_COMPILER_OPTION = 1007;
+ /**
+ * Status constant indicating that the attached jsdoc content cannot be retrieved due to multiple reasons: + * invalid url, timed-out,...
+ * + */ + public static final int CANNOT_RETRIEVE_ATTACHED_JSDOC = 1008; + /** + *Status constant indicating that the attached jsdoc content format is unrecognized.
+ * + */ + public static final int UNKNOWN_JSDOC_FORMAT = 1009; + /** + *Status constant indicating that the variable is deprecated.
+ * + */ + public static final int DEPRECATED_VARIABLE = 1010; +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptProject.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptProject.java new file mode 100644 index 0000000..7f363d7 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJavaScriptProject.java @@ -0,0 +1,846 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * IBM Corporation - added getOption(String, boolean), getOptions(boolean) and setOptions(Map) + * IBM Corporation - deprecated getPackageFragmentRoots(IIncludePathEntry) and + * added findPackageFragmentRoots(IIncludePathEntry) + * IBM Corporation - added isOnClasspath(IResource) + * IBM Corporation - added setOption(String, String) + * IBM Corporation - added forceClasspathReload(IProgressMonitor) + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.wst.jsdt.core.eval.IEvaluationContext; + +/** + * A JavaScript project represents a view of a project resource in terms of JavaScript + * elements such as package fragments, types, methods and fields. + * A project may contain several source folders (package roots), which contain source folders (package fragments). + * A package root corresponds to an underlying folder. + *+ * Each JavaScript project has a includepath, defining which folders contain source code and + * where required libraries are located. A project that + * references packages in another project can access the packages by including + * the required project in a includepath entry. The JavaScript model will present the + * source elements in the required project. The includepath format is a sequence of includepath entries + * describing the location and contents of package fragment roots. + *
+ * JavaScript project elements need to be opened before they can be navigated or manipulated. + * The children of a JavaScript project are the package fragment roots that are + * defined by the includepath and contained in this project (in other words, it + * does not include package fragment roots for other projects). + * + *
+ * This interface is not intended to be implemented by clients. An instance
+ * of one of these handles can be created via
+ * JavaScriptCore.create(project)
.
+ *
null
if unable to decode it
+ */
+ IIncludePathEntry decodeIncludepathEntry(String encodedEntry);
+
+ /**
+ * Encodes the given includepath entry into a string in the context of this project.
+ *
+ * @param includepathEntry the includepath entry to encode
+ * @return the encoded includepath entry
+ */
+ String encodeIncludepathEntry(IIncludePathEntry includepathEntry);
+
+ /**
+ * Returns the IJavaScriptElement
corresponding to the given
+ * includepath-relative path, or null
if no such
+ * IJavaScriptElement
is found. The result is one of an
+ * IJavaScriptUnit
, IClassFile
, or
+ * IPackageFragment
.
+ * + * When looking for a package fragment, there might be several potential + * matches; only one of them is returned. + * + *
For example, the path "java/lang/Object.js", would result in the
+ * IJavaScriptUnit
or IClassFile
corresponding to
+ * "java.lang.Object". The path "java/lang" would result in the
+ * IPackageFragment
for "java.lang".
+ * @param path the given includepath-relative path
+ * @exception JavaScriptModelException if the given path is null
+ * or absolute
+ * @return the IJavaScriptElement
corresponding to the given
+ * includepath-relative path, or null
if no such
+ * IJavaScriptElement
is found
+ */
+ IJavaScriptElement findElement(IPath path) throws JavaScriptModelException;
+
+ /**
+ * Returns the IJavaScriptElement
corresponding to the given
+ * includepath-relative path, or null
if no such
+ * IJavaScriptElement
is found. The result is one of an
+ * IJavaScriptUnit
, IClassFile
, or
+ * IPackageFragment
. If it is an IJavaScriptUnit
,
+ * its owner is the given owner.
+ *
+ * When looking for a package fragment, there might be several potential + * matches; only one of them is returned. + * + *
For example, the path "java/lang/Object.js", would result in the
+ * IJavaScriptUnit
or IClassFile
corresponding to
+ * "java.lang.Object". The path "java/lang" would result in the
+ * IPackageFragment
for "java.lang".
+ * @param path the given includepath-relative path
+ * @param owner the owner of the returned javaScript unit, ignored if it is
+ * not a javaScript unit.
+ * @exception JavaScriptModelException if the given path is null
+ * or absolute
+ * @return the IJavaScriptElement
corresponding to the given
+ * includepath-relative path, or null
if no such
+ * IJavaScriptElement
is found
+ */
+ IJavaScriptElement findElement(IPath path, WorkingCopyOwner owner) throws JavaScriptModelException;
+
+ /**
+ * Returns the first existing package fragment on this project's includepath
+ * whose path matches the given (absolute) path, or null
if none
+ * exist.
+ * The path can be:
+ * - internal to the workbench: "/Project/src"
+ * - external to the workbench: "c:/jdk/classes.zip/java/lang"
+ * @param path the given absolute path
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first existing package fragment on this project's includepath
+ * whose path matches the given (absolute) path, or null
if none
+ * exist
+ */
+ IPackageFragment findPackageFragment(IPath path) throws JavaScriptModelException;
+
+ /**
+ * Returns the existing package fragment root on this project's includepath
+ * whose path matches the given (absolute) path, or null
if
+ * one does not exist.
+ * The path can be:
+ * - internal to the workbench: "/Compiler/src"
+ * - external to the workbench: "c:/jdk/classes.zip"
+ * @param path the given absolute path
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the existing package fragment root on this project's includepath
+ * whose path matches the given (absolute) path, or null
if
+ * one does not exist
+ */
+ IPackageFragmentRoot findPackageFragmentRoot(IPath path)
+ throws JavaScriptModelException;
+ /**
+ * Returns the existing package fragment roots identified by the given entry.
+ * Note that a includepath entry that refers to another project may
+ * have more than one root (if that project has more than on root
+ * containing source), and includepath entries within the current
+ * project identify a single root.
+ *
+ * If the includepath entry denotes a variable, it will be resolved and return + * the roots of the target entry (empty if not resolvable). + *
+ * If the includepath entry denotes a container, it will be resolved and return
+ * the roots corresponding to the set of container entries (empty if not resolvable).
+ *
+ * @param entry the given entry
+ * @return the existing package fragment roots identified by the given entry
+ * @see IJsGlobalScopeContainer
+ */
+ IPackageFragmentRoot[] findPackageFragmentRoots(IIncludePathEntry entry);
+ /**
+ * Returns the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found.
+ * The fully qualified name is a dot-separated name. For example,
+ * a class B defined as a member type of a class A in package x.y should have a
+ * the fully qualified name "x.y.A.B".
+ *
+ * Note that in order to be found, a type name (or its toplevel enclosing
+ * type name) must match its corresponding javaScript unit name. As a
+ * consequence, secondary types cannot be found using this functionality.
+ * To find secondary types use {@link #findType(String, IProgressMonitor)} instead.
+ *
+ * @param fullyQualifiedName the given fully qualified name
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType findType(String fullyQualifiedName) throws JavaScriptModelException;
+
+ /**
+ * Returns all the types found following this project's include path with
+ * the given fully qualified name. The fully qualified name is a
+ * dot-separated name.
+ *
+ * @param fullyQualifiedName
+ * the given fully qualified name
+ * @exception JavaScriptModelException
+ * if this project does not exist or if an exception occurs
+ * while accessing its corresponding resource
+ * @return the types found following this project's include path with the
+ * given fully qualified name
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType[] findTypes(String fullyQualifiedName) throws JavaScriptModelException;
+
+ /**
+ * Same functionality as {@link #findType(String)} but also look for secondary
+ * types if given name does not match a javaScript unit name.
+ *
+ * @param fullyQualifiedName the given fully qualified name
+ * @param progressMonitor the progress monitor to report progress to,
+ * or null
if no progress monitor is provided
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaScriptModelException;
+ /**
+ * Returns the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found.
+ * The fully qualified name is a dot-separated name. For example,
+ * a class B defined as a member type of a class A in package x.y should have a
+ * the fully qualified name "x.y.A.B".
+ * If the returned type is part of a javaScript unit, its owner is the given
+ * owner.
+ *
+ * Note that in order to be found, a type name (or its toplevel enclosing
+ * type name) must match its corresponding javaScript unit name. As a
+ * consequence, secondary types cannot be found using this functionality.
+ * To find secondary types use {@link #findType(String, WorkingCopyOwner, IProgressMonitor)}
+ * instead.
+ *
+ * @param fullyQualifiedName the given fully qualified name
+ * @param owner the owner of the returned type's javaScript unit
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaScriptModelException;
+
+ /**
+ * Returns all the types found following this project's include path with
+ * the given fully qualified name. The fully qualified name is a
+ * dot-separated name.
+ *
+ * @param fullyQualifiedName
+ * the given fully qualified name
+ * @param owner
+ * the owner of the returned type's javaScript unit
+ * @exception JavaScriptModelException
+ * if this project does not exist or if an exception occurs
+ * while accessing its corresponding resource
+ * @return the types found following this project's include path with the
+ * given fully qualified name
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType[] findTypes(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaScriptModelException;
+ /**
+ * Same functionality as {@link #findType(String, WorkingCopyOwner)}
+ * but also look for secondary types if given name does not match
+ * a javaScript unit name.
+ *
+ * @param fullyQualifiedName the given fully qualified name
+ * @param owner the owner of the returned type's javaScript unit
+ * @param progressMonitor the progress monitor to report progress to,
+ * or null
if no progress monitor is provided
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaScriptModelException;
+ /**
+ * Returns the first type found following this project's includepath
+ * with the given package name and type qualified name
+ * or null
if none is found.
+ * The package name is a dot-separated name.
+ * The type qualified name is also a dot-separated name. For example,
+ * a class B defined as a member type of a class A should have the
+ * type qualified name "A.B".
+ *
+ * Note that in order to be found, a type name (or its toplevel enclosing
+ * type name) must match its corresponding javaScript unit name. As a
+ * consequence, secondary types cannot be found using this functionality.
+ * To find secondary types use {@link #findType(String, String, IProgressMonitor)}
+ * instead.
+ *
+ * @param packageName the given package name
+ * @param typeQualifiedName the given type qualified name
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given package name and type qualified name
+ * or null
if none is found
+ * @see IType#getTypeQualifiedName(char)
+ */
+ IType findType(String packageName, String typeQualifiedName) throws JavaScriptModelException;
+ /**
+ * Same functionality as {@link #findType(String, String)} but also look for
+ * secondary types if given name does not match a javaScript unit name.
+ *
+ * @param packageName the given package name
+ * @param typeQualifiedName the given type qualified name
+ * @param progressMonitor the progress monitor to report progress to,
+ * or null
if no progress monitor is provided
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaScriptModelException;
+ /**
+ * Returns the first type found following this project's includepath
+ * with the given package name and type qualified name
+ * or null
if none is found.
+ * The package name is a dot-separated name.
+ * The type qualified name is also a dot-separated name. For example,
+ * a class B defined as a member type of a class A should have the
+ * type qualified name "A.B".
+ * If the returned type is part of a javaScript unit, its owner is the given
+ * owner.
+ *
+ * Note that in order to be found, a type name (or its toplevel enclosing
+ * type name) must match its corresponding javaScript unit name. As a
+ * consequence, secondary types cannot be found using this functionality.
+ * To find secondary types use {@link #findType(String, String, WorkingCopyOwner, IProgressMonitor)}
+ * instead.
+ *
+ * @param packageName the given package name
+ * @param typeQualifiedName the given type qualified name
+ * @param owner the owner of the returned type's javaScript unit
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given package name and type qualified name
+ * or null
if none is found
+ * @see IType#getTypeQualifiedName(char)
+ */
+ IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaScriptModelException;
+ /**
+ * Same functionality as {@link #findType(String, String, WorkingCopyOwner)}
+ * but also look for secondary types if given name does not match a javaScript unit name.
+ *
+ * @param packageName the given package name
+ * @param typeQualifiedName the given type qualified name
+ * @param owner the owner of the returned type's javaScript unit
+ * @param progressMonitor the progress monitor to report progress to,
+ * or null
if no progress monitor is provided
+ * @exception JavaScriptModelException if this project does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return the first type found following this project's includepath
+ * with the given fully qualified name or null
if none is found
+ * @see IType#getFullyQualifiedName(char)
+ */
+ IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaScriptModelException;
+
+ /**
+ * Returns all of the existing package fragment roots that exist
+ * on the includepath, in the order they are defined by the includepath.
+ *
+ * @return all of the existing package fragment roots that exist
+ * on the includepath
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ IPackageFragmentRoot[] getAllPackageFragmentRoots() throws JavaScriptModelException;
+
+ /**
+ * Returns an array of non-JavaScript resources directly contained in this project.
+ * It does not transitively answer non-JavaScript resources contained in folders;
+ * these would have to be explicitly iterated over.
+ *
+ * Non-JavaScript resources includes other files and folders located in the + * project not accounted for by any of it source or binary package fragment + * roots. If the project is a source folder itself, resources excluded from the + * corresponding source includepath entry by one or more exclusion patterns + * are considered non-JavaScript resources and will appear in the result + * (possibly in a folder) + *
+ * + * @return an array of non-JavaScript resources (IFile
s and/or
+ * IFolder
s) directly contained in this project
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ Object[] getNonJavaScriptResources() throws JavaScriptModelException;
+
+ /**
+ * Helper method for returning one option value only. Equivalent to (String)this.getOptions(inheritJavaCoreOptions).get(optionName)
+ * Note that it may answer null
if this option does not exist, or if there is no custom value for it.
+ *
+ * For a complete description of the configurable options, see JavaScriptCore#getDefaultOptions
.
+ *
JavaScriptCore
.
+ *
+ * For a complete description of the configurable options, see JavaScriptCore#getDefaultOptions
.
+ *
String
; value type: String
)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ Map getOptions(boolean inheritJavaCoreOptions);
+
+ /**
+ * Returns a package fragment root for the file at the specified file system path.
+ * This is a handle-only method. The underlying java.io.File
+ * may or may not exist. No resource is associated with this local file
+ * package fragment root.
+ *
+ * @param filePath the file system path
+ * @return a package fragment root for the file at the specified file system path
+ */
+ IPackageFragmentRoot getPackageFragmentRoot(String filePath);
+
+ /**
+ * Returns a package fragment root for the given resource, which
+ * must either be a folder representing the top of a package hierarchy,
+ * or a javaScript file.
+ * This is a handle-only method. The underlying resource may or may not exist.
+ *
+ * @param resource the given resource
+ * @return a package fragment root for the given resource, which
+ * must either be a folder representing the top of a package hierarchy,
+ * or a javaScript file
+ */
+ IPackageFragmentRoot getPackageFragmentRoot(IResource resource);
+
+ /**
+ * Returns all of the package fragment roots contained in this
+ * project, identified on this project's resolved includepath. The result
+ * does not include package fragment roots in other projects referenced
+ * on this project's includepath.
+ *
+ * NOTE: This is equivalent to getChildren()
.
+ *
+ * @return all of the package fragment roots contained in this
+ * project, identified on this project's resolved includepath
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ IPackageFragmentRoot[] getPackageFragmentRoots() throws JavaScriptModelException;
+
+ /**
+ * Returns all package fragments in all package fragment roots contained
+ * in this project. This is a convenience method.
+ *
+ * Note that the package fragment roots corresponds to the resolved
+ * includepath of the project.
+ *
+ * @return all package fragments in all package fragment roots contained
+ * in this project
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+ IPackageFragment[] getPackageFragments() throws JavaScriptModelException;
+
+ /**
+ * Returns the IProject
on which this IJavaScriptProject
+ * was created. This is handle-only method.
+ *
+ * @return the IProject
on which this IJavaScriptProject
+ * was created
+ */
+ IProject getProject();
+
+ /**
+ * Returns the raw includepath for the project, as a list of includepath
+ * entries. This corresponds to the exact set of entries which were assigned
+ * using setRawIncludepath
, in particular such a includepath may
+ * contain includepath variable and includepath container entries. Includepath
+ * variable and includepath container entries can be resolved using the
+ * helper method getResolvedIncludepath
; includepath variable
+ * entries also can be resolved individually using
+ * JavaScriptCore#getIncludepathVariable
).
+ *
+ * Both includepath containers and includepath variables provides a level of
+ * indirection that can make the .jsdtScope
file stable across
+ * workspaces.
+ *
+ * Note that in case the project isn't yet opened, the includepath will + * be read directly from the associated .jsdtScope file. + *
+ * + * @return the raw includepath for the project, as a list of includepath entries + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @see IIncludePathEntry + */ + IIncludePathEntry[] getRawIncludepath() throws JavaScriptModelException; + + /** + * Returns the names of the projects that are directly required by this + * project. A project is required if it is in its includepath. + *+ * The project names are returned in the order they appear on the includepath. + * + * @return the names of the projects that are directly required by this + * project in includepath order + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + String[] getRequiredProjectNames() throws JavaScriptModelException; + + /** + * This is a helper method returning the resolved includepath for the project + * as a list of simple (non-variable, non-container) includepath entries. + * All includepath variable and includepath container entries in the project's + * raw includepath will be replaced by the simple includepath entries they + * resolve to. + *
+ * The resulting resolved includepath is accurate for the given point in time. + * If the project's raw includepath is later modified, or if includepath + * variables are changed, the resolved includepath can become out of date. + * Because of this, hanging on resolved includepath is not recommended. + *
+ * + * @param ignoreUnresolvedEntry indicates how to handle unresolvable + * variables and containers;true
indicates that missing
+ * variables and unresolvable includepath containers should be silently
+ * ignored, and that the resulting list should consist only of the
+ * entries that could be successfully resolved; false
indicates
+ * that a JavaScriptModelException
should be thrown for the first
+ * unresolved variable or container
+ * @return the resolved includepath for the project as a list of simple
+ * includepath entries, where all includepath variable and container entries
+ * have been resolved and substituted with their final target entries
+ * @exception JavaScriptModelException in one of the corresponding situation:
+ * ignoreUnresolvedEntry
is false
.true
if the given element is on the includepath of
+ * this project, false
otherwise
+ * @see IIncludePathEntry#getInclusionPatterns()
+ * @see IIncludePathEntry#getExclusionPatterns()
+ */
+ boolean isOnIncludepath(IJavaScriptElement element);
+ /**
+ * Returns whether the given resource is on the includepath of this project,
+ * that is, referenced from a includepath entry and not explicitly excluded
+ * using an exclusion pattern.
+ *
+ * @param resource the given resource
+ * @return true
if the given resource is on the includepath of
+ * this project, false
otherwise
+ * @see IIncludePathEntry#getInclusionPatterns()
+ * @see IIncludePathEntry#getExclusionPatterns()
+ */
+ boolean isOnIncludepath(IResource resource);
+
+ /**
+ * Creates a new evaluation context.
+ * @return a new evaluation context.
+ */
+ IEvaluationContext newEvaluationContext();
+
+ /**
+ * Creates and returns a type hierarchy for all types in the given
+ * region, considering subtypes within that region.
+ *
+ * @param monitor the given progress monitor
+ * @param region the given region
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @exception IllegalArgumentException if region is null
+ * @return a type hierarchy for all types in the given
+ * region, considering subtypes within that region
+ */
+ ITypeHierarchy newTypeHierarchy(IRegion region, IProgressMonitor monitor)
+ throws JavaScriptModelException;
+
+ /**
+ * Creates and returns a type hierarchy for all types in the given
+ * region, considering subtypes within that region and considering types in the
+ * working copies with the given owner.
+ * In other words, the owner's working copies will take
+ * precedence over their original javaScript units in the workspace.
+ * + * Note that if a working copy is empty, it will be as if the original javaScript + * unit had been deleted. + *
+ *
+ * @param monitor the given progress monitor
+ * @param region the given region
+ * @param owner the owner of working copies that take precedence over their original javaScript units
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @exception IllegalArgumentException if region is null
+ * @return a type hierarchy for all types in the given
+ * region, considering subtypes within that region
+ */
+ ITypeHierarchy newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)
+ throws JavaScriptModelException;
+
+ /**
+ * Creates and returns a type hierarchy for the given type considering
+ * subtypes in the specified region.
+ *
+ * @param type the given type
+ * @param region the given region
+ * @param monitor the given monitor
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ *
+ * @exception IllegalArgumentException if type or region is null
+ * @return a type hierarchy for the given type considering
+ * subtypes in the specified region
+ */
+ ITypeHierarchy newTypeHierarchy(
+ IType type,
+ IRegion region,
+ IProgressMonitor monitor)
+ throws JavaScriptModelException;
+
+ /**
+ * Creates and returns a type hierarchy for the given type considering
+ * subtypes in the specified region and considering types in the
+ * working copies with the given owner.
+ * In other words, the owner's working copies will take
+ * precedence over their original javaScript units in the workspace.
+ *
+ * Note that if a working copy is empty, it will be as if the original javaScript + * unit had been deleted. + *
+ *
+ * @param type the given type
+ * @param region the given region
+ * @param monitor the given monitor
+ * @param owner the owner of working copies that take precedence over their original javaScript units
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ *
+ * @exception IllegalArgumentException if type or region is null
+ * @return a type hierarchy for the given type considering
+ * subtypes in the specified region
+ */
+ ITypeHierarchy newTypeHierarchy(
+ IType type,
+ IRegion region,
+ WorkingCopyOwner owner,
+ IProgressMonitor monitor)
+ throws JavaScriptModelException;
+
+ /**
+ * Returns the raw includepath for the project as defined by its
+ * .jsdtScope
file from disk, or null
+ * if unable to read the file.
+ *
+ * This includepath may differ from the in-memory includepath returned by
+ * getRawIncludepath
, in case the automatic reconciliation
+ * mechanism has not been performed yet. Usually, any change to the
+ * .jsdtScope
file is automatically noticed and reconciled at
+ * the next resource change notification event. However, if the file is
+ * modified within an operation, where this change needs to be taken into
+ * account before the operation ends, then the includepath from disk can be
+ * read using this method, and further assigned to the project using
+ * setRawIncludepath(...)
.
+ *
+ * Includepath variable and includepath container entries can be resolved using
+ * the helper method getResolvedIncludepath
; includepath variable
+ * entries also can be resolved individually using
+ * JavaScriptCore#getIncludepathVariable
).
+ *
+ * Note that no check is performed whether the project has the JavaScript nature
+ * set, allowing an existing .jsdtScope
file to be considered
+ * independantly (unlike getRawIncludepath
which requires the
+ * JavaScript nature to be associated with the project).
+ *
+ * In order to manually force a project includepath refresh, one can simply
+ * assign the project includepath using the result of this method, as follows:
+ * proj.setRawIncludepath(proj.readRawIncludepath(), monitor)
+ * (note that the readRawIncludepath
method
+ * could return null
).
+ *
Map options = this.getOptions(false); map.put(optionName, optionValue); this.setOptions(map)
+ *
+ * For a complete description of the configurable options, see JavaScriptCore#getDefaultOptions
.
+ *
+ * For a complete description of the configurable options, see JavaScriptCore#getDefaultOptions
.
+ *
String
; value type: String
),
+ * or null
to flush all custom options (clients will automatically get the global JavaScriptCore options).
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ void setOptions(Map newOptions);
+
+ /**
+ * Sets the includepath of this project using a list of includepath entries. In particular such a includepath may contain
+ * includepath variable entries. Includepath variable entries can be resolved individually ({@link JavaScriptCore#getIncludepathVariable(String)}),
+ * or the full includepath can be resolved at once using the helper method {@link #getResolvedIncludepath(boolean)}.
+ * + *
+ * If it is specified that this operation cannot modify resources, the .jsdtScope file will not be written to disk
+ * and no error marker will be generated. To synchronize the .jsdtScope with the in-memory includepath,
+ * one can use setRawIncludepath(readRawIncludepath(), true, monitor)
.
+ *
+ * Setting the includepath to null
specifies a default includepath
+ * (the project root). Setting the includepath to an empty array specifies an
+ * empty includepath.
+ *
+ * If a cycle is detected while setting this includepath (and if resources can be modified), an error marker will be added + * to the project closing the cycle. + * To avoid this problem, use {@link #hasIncludepathCycle(IIncludePathEntry[])} + * before setting the includepath. + *
+ * This operation acquires a lock on the workspace's root. + * + * @param entries a list of includepath entries + * @param canModifyResources whether resources should be written to disk if needed + * @param monitor the given progress monitor + * @exception JavaScriptModelException if the includepath could not be set. Reasons include: + *
+ *
+ * Setting the includepath to null
specifies a default includepath
+ * (the project root). Setting the includepath to an empty array specifies an
+ * empty includepath.
+ *
+ * If a cycle is detected while setting this includepath, an error marker will be added + * to the project closing the cycle. + * To avoid this problem, use {@link #hasIncludepathCycle(IIncludePathEntry[])} + * before setting the includepath. + *
+ * This operation acquires a lock on the workspace's root. + * + * @param entries a list of includepath entries + * @param monitor the given progress monitor + * @exception JavaScriptModelException if the includepath could not be set. Reasons include: + *
+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IJavaScriptUnit extends ITypeRoot, ISourceManipulation { +/** + * Constant indicating that a reconcile operation should not return an AST. + */ +public static final int NO_AST = 0; + +/** + * Constant indicating that a reconcile operation should recompute the problems + * even if the source hasn't changed. + */ +public static final int FORCE_PROBLEM_DETECTION = 0x01; + +/** + * Constant indicating that a reconcile operation should enable the statements recovery. + * @see org.eclipse.wst.jsdt.core.dom.ASTParser#setStatementsRecovery(boolean) + */ +public static final int ENABLE_STATEMENTS_RECOVERY = 0x02; + +/** + * Constant indicating that a reconcile operation should enable the bindings recovery + * @see org.eclipse.wst.jsdt.core.dom.ASTParser#setBindingsRecovery(boolean) + * @see org.eclipse.wst.jsdt.core.dom.IBinding#isRecovered() + */ +public static final int ENABLE_BINDINGS_RECOVERY = 0x04; + + +/** + * Changes this javaScript file handle into a working copy. A new {@link IBuffer} is + * created using this javaScript file handle's owner. Uses the primary owner is none was + * specified when this javaScript file handle was created. + *+ * When switching to working copy mode, problems are reported to given + * {@link IProblemRequestor}. Note that once in working copy mode, the given + * {@link IProblemRequestor} is ignored. Only the original {@link IProblemRequestor} + * is used to report subsequent problems. + *
+ *+ * Once in working copy mode, changes to this javaScript file or its children are done in memory. + * Only the new buffer is affected. Using {@link #commitWorkingCopy(boolean, IProgressMonitor)} + * will bring the underlying resource in sync with this javaScript file. + *
+ *+ * If this JavaScript file was already in working copy mode, an internal counter is incremented and no + * other action is taken on this javaScript file. To bring this javaScript file back into the original mode + * (where it reflects the underlying resource), {@link #discardWorkingCopy} must be call as many + * times as {@link #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)}. + *
+ * + * @param problemRequestor a requestor which will get notified of problems detected during + * reconciling as they are discovered. The requestor can be set tonull
indicating
+ * that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this javaScript file
+ * or null
if no progress should be reported
+ * @throws JavaScriptModelException if this javaScript file could not become a working copy.
+ * @see #discardWorkingCopy()
+ *
+ * @deprecated Use {@link #becomeWorkingCopy(IProgressMonitor)} instead.
+ * Note that if this deprecated method is used, problems will be reported to the given problem requestor
+ * as well as the problem requestor returned by the working copy owner (if not null). While this may
+ * be desired in some situations, by and large it is not.
+*/
+void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Changes this javaScript file handle into a working copy. A new {@link IBuffer} is
+ * created using this javaScript file handle's owner. Uses the primary owner if none was
+ * specified when this javaScript file handle was created.
+ * + * When switching to working copy mode, problems are reported to the {@link IProblemRequestor + * problem requestor} of the {@link WorkingCopyOwner working copy owner}. + *
+ * Once in working copy mode, changes to this javaScript file or its children are done in memory. + * Only the new buffer is affected. Using {@link #commitWorkingCopy(boolean, IProgressMonitor)} + * will bring the underlying resource in sync with this javaScript file. + *
+ * If this javaScript file was already in working copy mode, an internal counter is incremented and no + * other action is taken on this javaScript file. To bring this javaScript file back into the original mode + * (where it reflects the underlying resource), {@link #discardWorkingCopy} must be call as many + * times as {@link #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)}. + *
+ * + * @param monitor a progress monitor used to report progress while opening this javaScript file + * ornull
if no progress should be reported
+ * @throws JavaScriptModelException if this javaScript file could not become a working copy.
+ * @see #discardWorkingCopy()
+ */
+void becomeWorkingCopy(IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Commits the contents of this working copy to its underlying resource.
+ *
+ * It is possible that the contents of the original resource have changed
+ * since this working copy was created, in which case there is an update conflict.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the contents of this working copy are applied to
+ * the underlying resource even though this working copy was created before
+ * a subsequent change in the resourcefalse
- in this case a {@link JavaScriptModelException} is throwncreateImport(name, Flags.AccDefault, sibling, monitor)
.
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of the import declaration to add + * @param sibling the existing element which the import declaration will be inserted immediately before (if + * null
, then this import will be inserted as the last import declaration.
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted import declaration (or the previously existing one in case attempting to create a duplicate)
+ *
+ * @throws JavaScriptModelException if the element could not be created. Reasons include:
+ * + * Optionally, the new element can be positioned before the specified + * sibling. If no sibling is specified, the element will be inserted + * as the last import declaration in this javaScript file. + *
+ * If the javaScript file already includes the specified import declaration, + * the import is not generated (it does not generate duplicates). + * + *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of the import declaration + * @param sibling the existing element which the import declaration will be inserted immediately before (if + * null
, then this import will be inserted as the last import declaration.
+ * @param flags {@link Flags#AccStatic} for static imports, or
+ * {@link Flags#AccDefault} for regular imports; other modifier flags
+ * are ignored
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted import declaration (or the previously existing one in case attempting to create a duplicate)
+ *
+ * @throws JavaScriptModelException if the element could not be created. Reasons include:
+ *
+ * Optionally, the new type can be positioned before the specified
+ * sibling. If sibling
is null
, the type will be appended
+ * to the end of this javaScript file.
+ *
+ *
It is possible that a type with the same name already exists in this javaScript file.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the type is created with the new contentsfalse
- in this case a {@link JavaScriptModelException} is thrownNote: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * + * @param contents the source contents of the type declaration to add. + * @param sibling the existing element which the type will be inserted immediately before (if + *null
, then this type will be inserted as the last type declaration.
+ * @param force a boolean
flag indicating how to deal with duplicates
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted type
+ *
+ * @throws JavaScriptModelException if the element could not be created. Reasons include:
+ *
+ * Optionally, the new var can be positioned before the specified
+ * sibling. If sibling
is null
, the var will be appended
+ * to the end of this javaScript file.
+ *
+ *
It is possible that a var with the same name already exists in this javaScript file.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the var is created with the new contentsfalse
- in this case a {@link JavaScriptModelException} is thrownnull
, then this var will be inserted as the last var declaration.
+ * @param force a boolean
flag indicating how to deal with duplicates
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted var
+ *
+ * @throws JavaScriptModelException if the element could not be created. Reasons include:
+ *
+ * Optionally, the new function can be positioned before the specified
+ * sibling. If sibling
is null
, the function will be appended
+ * to the end of this javaScript file.
+ *
+ *
It is possible that a function with the same name already exists in this javaScript file.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the function is created with the new contentsfalse
- in this case a {@link JavaScriptModelException} is thrownnull
, then this function will be inserted as the last function declaration.
+ * @param force a boolean
flag indicating how to deal with duplicates
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted function
+ *
+ * @throws JavaScriptModelException if the element could not be created. Reasons include:
+ * + * This has no effect if this javaScript file was not in working copy mode. + *
+ *+ * If {@link #becomeWorkingCopy} was called several times on this + * javaScript file, {@link #discardWorkingCopy} must be called as + * many times before it switches back to the original mode. + *
+ * + * @throws JavaScriptModelException if this working copy could not return in its original mode. + * @see #becomeWorkingCopy(IProblemRequestor, IProgressMonitor) + */ +void discardWorkingCopy() throws JavaScriptModelException; +/** + * Finds the elements in this javaScript file that correspond to + * the given element. + * An element A corresponds to an element B if: + *null
if no such javaScript elements can be found
+ * or if the given element is not included in a javaScript file.
+ *
+ * @param element the given element
+ * @return the found elements in this javaScript file that correspond to the given element
+ */
+IJavaScriptElement[] findElements(IJavaScriptElement element);
+/**
+ * Finds the working copy for this javaScript file, given a {@link WorkingCopyOwner}.
+ * If no working copy has been created for this javaScript file associated with this
+ * working copy owner, returns null
.
+ *
+ * Users of this method must not destroy the resulting working copy.
+ *
+ * @param owner the given {@link WorkingCopyOwner}
+ * @return the found working copy for this javaScript file, null
if none
+ * @see WorkingCopyOwner
+ */
+IJavaScriptUnit findWorkingCopy(WorkingCopyOwner owner);
+/**
+ * Returns all types declared in this javaScript file in the order
+ * in which they appear in the source.
+ * This includes all top-level types and nested member types.
+ * It does NOT include local types (types defined in methods).
+ *
+ * @return the array of top-level and member types defined in a javaScript file, in declaration order.
+ * @throws JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+IType[] getAllTypes() throws JavaScriptModelException;
+/**
+ * Returns the first import declaration in this javaScript file with the given name.
+ * This is a handle-only method. The import declaration may or may not exist. This
+ * is a convenience method - imports can also be accessed from a javaScript file's
+ * import container.
+ *
+ *
+ *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of the import to find + * @return a handle onto the corresponding import declaration. The import declaration may or may not exist. + */ +IImportDeclaration getImport(String name) ; +/** + * Returns the import container for this javaScript file. + * This is a handle-only method. The import container may or + * may not exist. The import container can used to access the + * imports. + * + *Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @return a handle onto the corresponding import container. The + * import contain may or may not exist. + */ +IImportContainer getImportContainer(); +/** + * Returns the import declarations in this javaScript file + * in the order in which they appear in the source. This is + * a convenience method - import declarations can also be + * accessed from a javaScript file's import container. + * + *Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @return the import declarations in this javaScript file + * @throws JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ +IImportDeclaration[] getImports() throws JavaScriptModelException; +/** + * Returns the primary javaScript file (whose owner is the primary owner) + * this working copy was created from, or this javaScript file if this a primary + * javaScript file. + *+ * Note that the returned primary javaScript file can be in working copy mode. + *
+ * + * @return the primary javaScript file this working copy was created from, + * or this javaScript file if it is primary + */ +IJavaScriptUnit getPrimary(); +/** + * Returns the working copy owner of this working copy. + * Returns null if it is not a working copy or if it has no owner. + * + * @return WorkingCopyOwner the owner of this working copy ornull
+ */
+WorkingCopyOwner getOwner();
+/**
+ * Returns the top-level types declared in this javaScript file
+ * in the order in which they appear in the source.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @return the top-level types declared in this javaScript file + * @throws JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ +IType[] getTypes() throws JavaScriptModelException; +/** + * Returns a new working copy of this javaScript file if it is a primary javaScript file, + * or this javaScript file if it is already a non-primary working copy. + *+ * Note: if intending to share a working copy amongst several clients, then + * {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)} + * should be used instead. + *
+ * When the working copy instance is created, an ADDED IJavaScriptElementDelta is + * reported on this working copy. + *
+ * Once done with the working copy, users of this method must discard it using + * {@link #discardWorkingCopy()}. + *
+ * Since 2.1, a working copy can be created on a not-yet existing compilation + * unit. In particular, such a working copy can then be committed in order to create + * the corresponding javaScript file. + *
+ * @param monitor a progress monitor used to report progress while opening this javaScript file + * ornull
if no progress should be reported
+ * @throws JavaScriptModelException if the contents of this element can
+ * not be determined.
+ * @return a new working copy of this element if this element is not
+ * a working copy, or this element if this element is already a working copy
+ */
+IJavaScriptUnit getWorkingCopy(IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Returns a shared working copy on this javaScript file using the given working copy owner to create
+ * the buffer, or this javaScript file if it is already a non-primary working copy.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original javaScript file AND was using the same working copy owner (that is, as defined by {@link Object#equals}).
+ * + * The life time of a shared working copy is as follows: + *
+ * Note that the working copy owner will be used for the life time of this working copy, that is if the + * working copy is closed then reopened, this owner will be used. + * The buffer will be automatically initialized with the original's javaScript file content + * upon creation. + *
+ * When the shared working copy instance is created, an ADDED IJavaScriptElementDelta is reported on this + * working copy. + *
+ * Since 2.1, a working copy can be created on a not-yet existing compilation + * unit. In particular, such a working copy can then be committed in order to create + * the corresponding javaScript file. + *
+ * @param owner the working copy owner that creates a buffer that is used to get the content + * of the working copy + * @param problemRequestor a requestor which will get notified of problems detected during + * reconciling as they are discovered. The requestor can be set tonull
indicating
+ * that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this javaScript file
+ * or null
if no progress should be reported
+ * @throws JavaScriptModelException if the contents of this element can
+ * not be determined.
+ * @return a new working copy of this element using the given factory to create
+ * the buffer, or this element if this element is already a working copy
+ * @deprecated Use {@link ITypeRoot#getWorkingCopy(WorkingCopyOwner, IProgressMonitor)} instead.
+ * Note that if this deprecated method is used, problems will be reported on the passed problem requester
+ * as well as on the problem requestor returned by the working copy owner (if not null).
+*/
+IJavaScriptUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Returns whether the resource of this working copy has changed since the
+ * inception of this working copy.
+ * Returns false
if this javaScript file is not in working copy mode.
+ *
+ * @return whether the resource has changed
+ */
+public boolean hasResourceChanged();
+/**
+ * Returns whether this element is a working copy.
+ *
+ * @return true if this element is a working copy, false otherwise
+ */
+boolean isWorkingCopy();
+
+/**
+ * Reconciles the contents of this working copy, sends out a JavaScript delta
+ * notification indicating the nature of the change of the working copy since
+ * the last time it was either reconciled or made consistent
+ * ({@link IOpenable#makeConsistent(IProgressMonitor)}), and returns a
+ * javaScript file AST if requested.
+ * + * It performs the reconciliation by locally caching the contents of + * the working copy, updating the contents, then creating a delta + * over the cached contents and the new contents, and finally firing + * this delta. + *
+ * The boolean argument allows to force problem detection even if the + * working copy is already consistent. + *
+ *
+ * This functionality allows to specify a working copy owner which is used
+ * during problem detection. All references contained in the working copy are
+ * resolved against other units; for which corresponding owned working copies
+ * are going to take precedence over their original javaScript files. If
+ * null
is passed in, then the primary working copy owner is used.
+ *
+ * Compilation problems found in the new contents are notified through the + * {@link IProblemRequestor} interface which was passed at + * creation, and no longer as transient markers. + *
+ *+ * Note: Since 3.0, added/removed/changed inner types generate change deltas. + *
+ *
+ * If requested, a DOM AST representing the javaScript file is returned.
+ * Its bindings are computed only if the problem requestor is active, or if the
+ * problem detection is forced. This method returns null
if the
+ * creation of the DOM AST was not requested, or if the requested level of AST
+ * API is not supported, or if the working copy was already consistent.
+ *
+ * This method doesn't perform statements recovery. To recover statements with syntax + * errors, {@link #reconcile(int, boolean, boolean, WorkingCopyOwner, IProgressMonitor)} must be use. + *
+ * + * @param astLevel either {@link #NO_AST} if no AST is wanted, + * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted + * @param forceProblemDetection boolean indicating whether problem should be + * recomputed even if the source hasn't changed + * @param owner the owner of working copies that take precedence over the + * original javaScript files, ornull
if the primary working
+ * copy owner should be used
+ * @param monitor a progress monitor
+ * @return the javaScript file AST or null
if not requested,
+ * or if the requested level of AST API is not supported,
+ * or if the working copy was consistent
+ * @throws JavaScriptModelException if the contents of the original element
+ * cannot be accessed. Reasons include:
+ * + * It performs the reconciliation by locally caching the contents of + * the working copy, updating the contents, then creating a delta + * over the cached contents and the new contents, and finally firing + * this delta. + *
+ * The boolean argument allows to force problem detection even if the + * working copy is already consistent. + *
+ *
+ * This functionality allows to specify a working copy owner which is used
+ * during problem detection. All references contained in the working copy are
+ * resolved against other units; for which corresponding owned working copies
+ * are going to take precedence over their original javaScript files. If
+ * null
is passed in, then the primary working copy owner is used.
+ *
+ * Compilation problems found in the new contents are notified through the + * {@link IProblemRequestor} interface which was passed at + * creation, and no longer as transient markers. + *
+ *+ * Note: Since 3.0, added/removed/changed inner types generate change deltas. + *
+ *
+ * If requested, a DOM AST representing the javaScript file is returned.
+ * Its bindings are computed only if the problem requestor is active, or if the
+ * problem detection is forced. This method returns null
if the
+ * creation of the DOM AST was not requested, or if the requested level of AST
+ * API is not supported, or if the working copy was already consistent.
+ *
+ * If statements recovery is enabled then this method tries to rebuild statements + * with syntax error. Otherwise statements with syntax error won't be present in + * the returning DOM AST. + *
+ * + * @param astLevel either {@link #NO_AST} if no AST is wanted, + * or the {@linkplain org.eclipse.wst.jsdt.core.dom.AST#newAST(int) AST API level} of the AST if one is wanted + * @param forceProblemDetection boolean indicating whether problem should be + * recomputed even if the source hasn't changed + * @param enableStatementsRecovery iftrue
statements recovery is enabled.
+ * @param owner the owner of working copies that take precedence over the
+ * original javaScript files, or null
if the primary working
+ * copy owner should be used
+ * @param monitor a progress monitor
+ * @return the javaScript file AST or null
if not requested,
+ * or if the requested level of AST API is not supported,
+ * or if the working copy was consistent
+ * @throws JavaScriptModelException if the contents of the original element
+ * cannot be accessed. Reasons include:
+ * + * If the problem detection is forced by passing the {@link #FORCE_PROBLEM_DETECTION} bit in the given reconcile flag, + * problem detection is run even if the working copy is already consistent. + *
+ * + *+ * It performs the reconciliation by locally caching the contents of + * the working copy, updating the contents, then creating a delta + * over the cached contents and the new contents, and finally firing + * this delta.
+ * + *
+ * This functionality allows to specify a working copy owner which is used
+ * during problem detection. All references contained in the working copy are
+ * resolved against other units; for which corresponding owned working copies
+ * are going to take precedence over their original javaScript files. If
+ * null
is passed in, then the primary working copy owner is used.
+ *
+ * Compilation problems found in the new contents are notified through the + * {@link IProblemRequestor} interface which was passed at + * creation, and no longer as transient markers. + *
+ *+ * Note: Since 3.0, added/removed/changed inner types generate change deltas. + *
+ *
+ * If requested, a DOM AST representing the javaScript file is returned.
+ * Its bindings are computed only if the problem requestor is active, or if the
+ * problem detection is forced. This method returns null
if the
+ * creation of the DOM AST was not requested, or if the requested level of AST
+ * API is not supported, or if the working copy was already consistent.
+ *
+ * If statements recovery is enabled by passing the {@link #ENABLE_STATEMENTS_RECOVERY} bit in the given reconcile flag + * then this method tries to rebuild statements with syntax error. Otherwise statements with syntax error won't be + * present in the returning DOM AST.
+ *+ * If bindings recovery is enabled by passing the {@link #ENABLE_BINDINGS_RECOVERY} bit in the given reconcile flag + * then this method tries to resolve bindings even if the type resolution contains errors.
+ *+ * The given reconcile flags is a bit-mask of the different constants ({@link #ENABLE_BINDINGS_RECOVERY}, + * {@link #ENABLE_STATEMENTS_RECOVERY}, {@link #FORCE_PROBLEM_DETECTION}). Unspecified values are left for future use. + *
+ * + * @param astLevel either {@link #NO_AST} if no AST is wanted, + * or the {@linkplain org.eclipse.wst.jsdt.core.dom.AST#newAST(int) AST API level} of the AST if one is wanted + * @param reconcileFlags the given reconcile flags + * @param owner the owner of working copies that take precedence over the + * original javaScript files, ornull
if the primary working
+ * copy owner should be used
+ * @param monitor a progress monitor
+ * @return the javaScript file AST or null
if not requested,
+ * or if the requested level of AST API is not supported,
+ * or if the working copy was consistent
+ * @throws JavaScriptModelException if the contents of the original element
+ * cannot be accessed. Reasons include:
+ * Note: This is the inverse of committing the content of the + * working copy to the original element with {@link #commitWorkingCopy(boolean, IProgressMonitor)}. + * + * @throws JavaScriptModelException if the contents of the original element + * cannot be accessed. Reasons include: + *
null
if no such function can be found
+ * or if the given element is not included in a javaScript file.
+ *
+ * @param function the given function
+ * @return the found functions in this javaScript file that correspond to the given function
+ */
+IFunction[] findFunctions(IFunction function);
+
+
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJsGlobalScopeContainer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJsGlobalScopeContainer.java
new file mode 100644
index 0000000..2976cb1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJsGlobalScopeContainer.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Interface of a includepath container.
+ * A includepath container provides a way to indirectly reference a set of includepath entries through
+ * a includepath entry of kind CPE_CONTAINER
. Typically, a includepath container can
+ * be used to describe a complex library composed of filess or projects, considering also
+ * that containers can map to different set of entries on each project, in other words, several
+ * projects can reference the same generic container path, but have each of them actually bound
+ * to a different container object.
+ * + * The set of entries associated with a includepath container may contain any of the following: + *
CPE_LIBRARY
) CPE_PROJECT
)
+ * Classpath container values are persisted locally to the workspace, but are not preserved from a
+ * session to another. It is thus highly recommended to register a JsGlobalScopeContainerInitializer
+ * for each referenced container (through the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer").
+ *
+ * @see IIncludePathEntry + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsGlobalScopeContainer { + + /** + * Kind for a container mapping to an application library + */ + int K_APPLICATION = 1; + + /** + * Kind for a container mapping to a system library + */ + int K_SYSTEM = 2; + + /** + * Kind for a container mapping to a default system library, implicitly contributed by the runtime + */ + int K_DEFAULT_SYSTEM = 3; + + /** + * Answers the set of includepath entries this container is mapping to. + *
+ * The set of entries associated with a includepath container may contain any of the following: + *
CPE_LIBRARY
) CPE_PROJECT
) + * This method is called by the JavaScript model when it needs to resolve this + * includepath container entry into a list of library and project entries. + * The method is typically called exactly once for a given JavaScript project, + * and the resulting list of entries cached internally by the JavaScript model. + * This method must not be called by other clients. + *
+ * There are a wide variety of conditions under which this method may be + * invoked. To ensure that the implementation does not interfere with + * correct functioning of the JavaScript model, the implementation should use + * only the following JavaScript model APIs: + *
K_APPLICATION
if this container maps to an application libraryK_SYSTEM
if this container maps to a system libraryK_DEFAULT_SYSTEM
if this container maps to a default system library (library
+ * implicitly contributed by the runtime).
+ * The container ID is also used to identify aJsGlobalScopeContainerInitializer
+ * registered on the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer", which can
+ * be invoked if needing to resolve the container before it is explicitly set.
+ *
+ * @return IPath - the container path that is associated with this container
+ */
+ IPath getPath();
+
+ /**
+ * Allows mapping between HTML imports and a toolkit's actual page imports. Implementers
+ * should ensure the validity of the imports before returning a value.
+ */
+ String[] resolvedLibraryImport(String a);
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJsGlobalScopeContainerInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJsGlobalScopeContainerInitializer.java
new file mode 100644
index 0000000..3b47c5e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IJsGlobalScopeContainerInitializer.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/**
+ *
+ */
+package org.eclipse.wst.jsdt.core;
+
+import java.net.URI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.jsdt.core.compiler.libraries.LibraryLocation;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IJsGlobalScopeContainerInitializer {
+ /**
+ * Binds a includepath container to a IJsGlobalScopeContainer
for a given project,
+ * or silently fails if unable to do so.
+ *
+ * A container is identified by a container path, which must be formed of two segments. + * The first segment is used as a unique identifier (which this initializer did register onto), and + * the second segment can be used as an additional hint when performing the resolution. + *
+ * The initializer is invoked if a container path needs to be resolved for a given project, and no
+ * value for it was recorded so far. The implementation of the initializer would typically set the
+ * corresponding container using JavaScriptCore#setJsGlobalScopeContainer
.
+ *
+ * A container initialization can be indirectly performed while attempting to resolve a project
+ * includepath using IJavaScriptProject#getResolvedClasspath(
; or directly when using
+ * JavaScriptCore#getJsGlobalScopeContainer
. During the initialization process, any attempt
+ * to further obtain the same container will simply return null
so as to avoid an
+ * infinite regression of initializations.
+ *
+ * A container initialization may also occur indirectly when setting a project includepath, as the operation + * needs to resolve the includepath for validation purpose. While the operation is in progress, a referenced + * container initializer may be invoked. If the initializer further tries to access the referring project includepath, + * it will not see the new assigned includepath until the operation has completed. Note that once the JavaScript + * change notification occurs (at the end of the operation), the model has been updated, and the project + * includepath can be queried normally. + *
+ * This method is called by the JavaScript model to give the party that defined + * this particular kind of includepath container the chance to install + * includepath container objects that will be used to convert includepath + * container entries into simpler includepath entries. The method is typically + * called exactly once for a given JavaScript project and includepath container + * entry. This method must not be called by other clients. + *
+ * There are a wide variety of conditions under which this method may be + * invoked. To ensure that the implementation does not interfere with + * correct functioning of the JavaScript model, the implementation should use + * only the following JavaScript model APIs: + *
true
if this container initializer can be requested to perform updates
+ * on its own container values. If so, then an update request will be performed using
+ * JsGlobalScopeContainerInitializer#requestJsGlobalScopeContainerUpdate
/
+ *
+ * @param containerPath the path of the container which requires to be updated
+ * @param project the project for which the container is to be updated
+ * @return returns true
if the container can be updated
+ */
+ public abstract boolean canUpdateJsGlobalScopeContainer(IPath containerPath, IJavaScriptProject project);
+
+ /**
+ * Request a registered container definition to be updated according to a container suggestion. The container suggestion
+ * only acts as a place-holder to pass along the information to update the matching container definition(s) held by the
+ * container initializer. In particular, it is not expected to store the container suggestion as is, but rather adjust
+ * the actual container definition based on suggested changes.
+ *
+ * IMPORTANT: In reaction to receiving an update request, a container initializer will update the corresponding
+ * container definition (after reconciling changes) at its earliest convenience, using
+ * JavaScriptCore#setJsGlobalScopeContainer(IPath, IJavaScriptProject[], IJsGlobalScopeContainer[], IProgressMonitor)
.
+ * Until it does so, the update will not be reflected in the JavaScript Model.
+ *
+ * In order to anticipate whether the container initializer allows to update its containers, the predicate
+ * JavaScriptCore#canUpdateJsGlobalScopeContainer
should be used.
+ *
+ * @param containerPath the path of the container which requires to be updated
+ * @param project the project for which the container is to be updated
+ * @param containerSuggestion a suggestion to update the corresponding container definition
+ * @throws CoreException when JavaScriptCore#setJsGlobalScopeContainer
would throw any.
+ * @see JavaScriptCore#setJsGlobalScopeContainer(IPath, IJavaScriptProject[], IJsGlobalScopeContainer[], org.eclipse.core.runtime.IProgressMonitor)
+ * @see JsGlobalScopeContainerInitializer#canUpdateJsGlobalScopeContainer(IPath, IJavaScriptProject)
+ */
+ public abstract void requestJsGlobalScopeContainerUpdate(IPath containerPath, IJavaScriptProject project, IJsGlobalScopeContainer containerSuggestion)
+ throws CoreException;
+
+ /**
+ * Returns a readable description for a container path. A readable description for a container path can be
+ * used for improving the display of references to container, without actually needing to resolve them.
+ * A good implementation should answer a description consistent with the description of the associated
+ * target container (see IJsGlobalScopeContainer.getDescription()
).
+ *
+ * @param containerPath the path of the container which requires a readable description
+ * @param project the project from which the container is referenced
+ * @return a string description of the container
+ */
+ public abstract String getDescription(IPath containerPath, IJavaScriptProject project);
+
+ /**
+ * Returns a includepath container that is used after this initializer failed to bind a includepath container
+ * to a IJsGlobalScopeContainer
for the given project. A non-null
+ * failure container indicates that there will be no more request to initialize the given container
+ * for the given project.
+ *
+ * By default a non-null
failure container with no includepath entries is returned.
+ * Clients wishing to get a chance to run the initializer again should override this method
+ * and return null
.
+ *
null
if wishing to run the initializer again
+ */
+ public abstract IJsGlobalScopeContainer getFailureContainer(final IPath containerPath, IJavaScriptProject project);
+
+ /**
+ * Returns an object which identifies a container for comparison purpose. This allows
+ * to eliminate redundant containers when accumulating includepath entries (e.g.
+ * runtime includepath computation). When requesting a container comparison ID, one
+ * should ensure using its corresponding container initializer. Indeed, a random container
+ * initializer cannot be held responsible for determining comparison IDs for arbitrary
+ * containers.
+ *
+ * @param containerPath the path of the container which is being checked
+ * @param project the project for which the container is to being checked
+ * @return returns an Object identifying the container for comparison
+ */
+ public abstract Object getComparisonID(IPath containerPath, IJavaScriptProject project);
+
+ public abstract URI getHostPath(IPath path, IJavaScriptProject project);
+
+ LibraryLocation getLibraryLocation();
+ /*
+ * Returns if this library allows attachment of external JsDoc
+ */
+ boolean allowAttachJsDoc();
+ /**
+ * returns a String of all SuperTypes provided by this library.
+ */
+ String[] containerSuperTypes();
+
+ /**
+ * Get the id of the inference provider for this library
+ * @return inference provider id
+ */
+ String getInferenceID();
+
+ void removeFromProject(IJavaScriptProject project);
+}
\ No newline at end of file
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ILocalVariable.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ILocalVariable.java
new file mode 100644
index 0000000..c13248f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ILocalVariable.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * Represents a local variable declared in a method..
+ * ILocalVariable
are pseudo-elements created as the result of a ICodeAssist.codeSelect(...)
+ * operation. They are not part of the JavaScript model (exists()
returns whether the parent exists rather than
+ * whether the local variable exists in the parent) and they are not included in the children of an IFunction
+ * or an IInitializer
.
+ *
+ * In particular such a pseudo-element should not be used as a handle. For example its name range won't be updated + * if the underlying source changes. + *
+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ILocalVariable extends IJavaScriptElement, ISourceReference { + + /** + * Returns the name of this local variable. + * + * @return the name of this local variable. + */ + String getElementName(); + + /** + * Returns the source range of this local variable's name. + * + * @return the source range of this local variable's name + */ + ISourceRange getNameRange(); + + /** + * Returns the type signature of this local variable. + *+ * The type signature may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @return the type signature of this local variable. + * @see Signature + */ + String getTypeSignature(); + /** + * Returns the JSDoc range if this element is from source, null otherwise. + * + *If this element is from source, the jsdoc range is + * extracted from the corresponding source.
+ *If this element's openable is not consistent, then null is returned.
+ * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return a source range corresponding to the jsdoc source ornull
+ * if no source is available, this element has no jsdoc comment or
+ * this element's openable is not consistent
+ * @see IOpenable#isConsistent()
+ */
+ ISourceRange getJSdocRange() throws JavaScriptModelException;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ILookupScope.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ILookupScope.java
new file mode 100644
index 0000000..0abb85e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ILookupScope.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.wst.jsdt.internal.core.NameLookup;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+
+public interface ILookupScope {
+ /*
+ * Returns a new name lookup. This name lookup first looks in the given working copies.
+ */
+ public NameLookup newNameLookup(IJavaScriptUnit[] workingCopies) throws JavaScriptModelException;
+
+ /*
+ * Returns a new name lookup. This name lookup first looks in the working copies of the given owner.
+ */
+ public NameLookup newNameLookup(WorkingCopyOwner owner) throws JavaScriptModelException ;
+
+ /*
+ * Returns a new search name environment for this project. This name environment first looks in the given working copies.
+ */
+ public SearchableEnvironment newSearchableNameEnvironment(IJavaScriptUnit[] workingCopies) throws JavaScriptModelException ;
+
+ /*
+ * Returns a new search name environment for this project. This name environment first looks in the working copies
+ * of the given owner.
+ */
+ public SearchableEnvironment newSearchableNameEnvironment(WorkingCopyOwner owner) throws JavaScriptModelException;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IMember.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IMember.java
new file mode 100644
index 0000000..b308c52
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IMember.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * Common protocol for JavaScript elements that can be members of javaScript files or types.
+ * This set consists of IType
, IFunction
,
+ * IField
, and IInitializer
.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IMember extends IJavaScriptElement, ISourceReference, ISourceManipulation, IParent { +/** + * Returns the categories defined by this member's JSDoc. A category is the identifier + * following the tag@category
in the member's JSDoc.
+ * Returns an empty array if no category is defined in this member's JSDoc.
+ *
+ * @return the categories defined by this member's doc
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ */
+String[] getCategories() throws JavaScriptModelException;
+/*
+ * Returns the class file in which this member is declared, or null
+ * if this member is not declared in a class file (for example, a source type).
+ * This is a handle-only method.
+ *
+ * @return the class file in which this member is declared, or null
+ * if this member is not declared in a class file (for example, a source type)
+ */
+IClassFile getClassFile();
+/**
+ * Returns the javaScript unit in which this member is declared, or null
+ * if this member is not declared in a javaScript unit.
+ * This is a handle-only method.
+ *
+ * @return the javaScript unit in which this member is declared, or null
+ * if this member is not declared in a javaScript unit (for example, a binary type)
+ */
+IJavaScriptUnit getJavaScriptUnit();
+/**
+ * Returns the type in which this member is declared, or null
+ * if this member is not declared in a type (for example, a top-level type).
+ * This is a handle-only method.
+ *
+ * @return the type in which this member is declared, or null
+ * if this member is not declared in a type (for example, a top-level type)
+ */
+IType getDeclaringType();
+/**
+ * Returns the modifier flags for this member. The flags can be examined using class
+ * Flags
.
+ *
+ * Note that only flags as indicated in the source are returned. Thus if an interface
+ * defines a method void myMethod();
the flags don't include the
+ * 'public' flag.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the modifier flags for this member
+ * @see Flags
+ */
+int getFlags() throws JavaScriptModelException;
+/**
+ * Returns the JSDoc range if this element is from source or if this element
+ * is a binary element with an attached source, null otherwise.
+ *
+ *
If this element is from source, the jsdoc range is + * extracted from the corresponding source.
+ *If this element is from a binary, the jsdoc is extracted from the + * attached source if present.
+ *If this element's openable is not consistent, then null is returned.
+ * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return a source range corresponding to the jsdoc source ornull
+ * if no source is available, this element has no jsdoc comment or
+ * this element's openable is not consistent
+ * @see IOpenable#isConsistent()
+ */
+ISourceRange getJSdocRange() throws JavaScriptModelException;
+/**
+ * Returns the source range of this member's simple name,
+ * or null
if this member does not have a name
+ * (for example, an initializer), or if this member does not have
+ * associated source code (for example, a binary type).
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the source range of this member's simple name,
+ * or null
if this member does not have a name
+ * (for example, an initializer), or if this member does not have
+ * associated source code (for example, a binary type)
+ */
+ISourceRange getNameRange() throws JavaScriptModelException;
+/**
+ * Returns the position relative to the order this member is defined in the source.
+ * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0).
+ * + * Two members m1 and m2 that are equal (e.g. 2 fields with the same name in + * the same type) can be distinguished using their occurrence counts. If member + * m1 appears first in the source, it will have an occurrence count of 1. If member + * m2 appears right after member m1, it will have an occurrence count of 2. + *
+ * The occurrence count can be used to distinguish initializers inside a type + * or anonymous types inside a method. + *
+ * This is a handle-only method. The member may or may not be present. + *
+ * + * @return the position relative to the order this member is defined in the source + */ +int getOccurrenceCount(); +/** + * Returns the JavaScript type root in which this member is declared. + * This is a handle-only method. + * + * @return the JavaScript type root in which this member is declared. + */ +ITypeRoot getTypeRoot(); +/** + * Returns the local or anonymous type declared in this source member with the given simple name and/or + * with the specified position relative to the order they are defined in the source. + * The name is empty if it is an anonymous type. + * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0). + * This is a handle-only method. The type may or may not exist. + * Throws aRuntimeException
if this member is not a source member.
+ *
+ * @param name the given simple name
+ * @param occurrenceCount the specified position
+ * @return the type with the given name and/or with the specified position relative to the order they are defined in the source
+ */
+IType getType(String name, int occurrenceCount);
+/**
+ * Returns whether this member is from a non-editable file.
+ * This is a handle-only method.
+ *
+ * @return true
if from a non-editable file, and false
if
+ * from a javaScript unit
+ */
+boolean isBinary();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IOpenable.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IOpenable.java
new file mode 100644
index 0000000..2b28286
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IOpenable.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Common protocol for JavaScript elements that must be opened before they can be
+ * navigated or modified. Opening a textual element (such as a javaScript file)
+ * involves opening a buffer on its contents. While open, any changes to the buffer
+ * can be reflected in the element's structure;
+ * see {@link #isConsistent} and {@link #makeConsistent(IProgressMonitor)}.
+ * + * To reduce complexity in clients, elements are automatically opened + * by the JavaScript model as element properties are accessed. The JavaScript model maintains + * an LRU cache of open elements, and automatically closes elements as they + * are swapped out of the cache to make room for other elements. Elements with + * unsaved changes are never removed from the cache, and thus, if the client + * maintains many open elements with unsaved + * changes, the LRU cache can grow in size (in this case the cache is not + * bounded). However, as elements are saved, the cache will shrink back to its + * original bounded size. + *
+ *+ * To open an element, all openable parent elements must be open. + * The JavaScript model automatically opens parent elements, as it automatically opens elements. + * Opening an element may provide access to direct children and other descendants, + * but does not automatically open any descendents which are themselves {@link IOpenable}. + * For example, opening a compilation unit provides access to all its constituent elements, + * but opening a package fragment does not open all compilation units in the package fragment. + *
+ *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IOpenable { + +/** + * Closes this element and its buffer (if any). + * Closing an element which is not open has no effect. + * + *Note: although {@link #close} is exposed in the API, clients are
+ * not expected to open and close elements - the JavaScript model does this automatically
+ * as elements are accessed.
+ *
+ * @exception JavaScriptModelException if an error occurs closing this element
+ */
+public void close() throws JavaScriptModelException;
+/**
+ * Finds and returns the recommended line separator for this element.
+ * The element's buffer is first searched and the first line separator in this buffer is returned if any.
+ * Otherwise the preference {@link org.eclipse.core.runtime.Platform#PREF_LINE_SEPARATOR}
+ * on this element's project or workspace is returned.
+ * Finally if no such preference is set, the system line separator is returned.
+ *
+ * @return the recommended line separator for this element
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ */
+public String findRecommendedLineSeparator() throws JavaScriptModelException;
+/**
+ * Returns the buffer opened for this element, or null
+ * if this element does not have a buffer.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the buffer opened for this element, or null
+ * if this element does not have a buffer
+ */
+public IBuffer getBuffer() throws JavaScriptModelException;
+/**
+ * Returns true
if this element is open and:
+ *
true
if this element is open and:
+ * NOTE: Child consistency is not considered. For example, a package fragment
+ * responds true
when it knows about all of its
+ * compilation units present in its underlying folder. However, one or more of
+ * the compilation units could be inconsistent.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return true if the element is consistent with its underlying resource or buffer, false otherwise.
+ * @see IOpenable#makeConsistent(IProgressMonitor)
+ */
+boolean isConsistent() throws JavaScriptModelException;
+/**
+ * Returns whether this openable is open. This is a handle-only method.
+ * @return true if this openable is open, false otherwise
+ */
+boolean isOpen();
+/**
+ * Makes this element consistent with its underlying resource or buffer
+ * by updating the element's structure and properties as necessary.
+ *
+ * Note: Using this functionality on a working copy will interfere with any + * subsequent reconciling operation. Indeed, the next + * {@link IJavaScriptUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)} or + * {@link IJavaScriptUnit#reconcile(int, boolean, boolean, WorkingCopyOwner, IProgressMonitor)} + * operation will not account for changes which occurred before an + * explicit use of {@link #makeConsistent(IProgressMonitor)} + *
+ * @param progress the given progress monitor + * @exception JavaScriptModelException if the element is unable to access the contents + * of its underlying resource. Reasons include: + *
Note: although {@link #open} is exposed in the API, clients are + * not expected to open and close elements - the JavaScript model does this automatically + * as elements are accessed. + * + * @param progress the given progress monitor + * @exception JavaScriptModelException if an error occurs accessing the contents + * of its underlying resource. Reasons include: + *
+ * The force
parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If false
is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no
+ * unintended data loss; it is the recommended setting.
+ * However, if true
is specified, an attempt will be made
+ * to write a corresponding file in the local file system,
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked
+ * as being local (even if it wasn't before).
+ *
+ * As a result of this operation, the element is consistent with its underlying + * resource or buffer. + * + * @param progress the given progress monitor + * @param force it controls how this method deals with + * cases where the workbench is not completely in sync with the local file system + * @exception JavaScriptModelException if an error occurs accessing the contents + * of its underlying resource. Reasons include: + *
+ * Package fragments elements need to be opened before they can be navigated or manipulated.
+ * The children are of type IJavaScriptUnit
(representing a source file) or
+ * IClassFile
(representing a read-only file).
+ * The children are listed in no particular order.
+ *
+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IPackageFragment extends IParent, IJavaScriptElement, IOpenable, ISourceManipulation { + + /** + *
+ * The name of package fragment for the default package (value: the empty
+ * string, ""
).
+ *
It is possible that a javaScript unit with the same name already exists in this
+ * package fragment.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the compilation is created with the new contentsfalse
- in this case a JavaScriptModelException
is thrownCoreException
occurred while creating an underlying resource
+ * null
(INVALID_CONTENTS)
+ * Note: it is possible that a package fragment contains only
+ * javaScript units (in other words, its kind is K_SOURCE
), in
+ * which case this method returns an empty collection.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return all of the files in this source folder
+ */
+ IClassFile[] getClassFiles() throws JavaScriptModelException;
+ /**
+ * Returns the javaScript unit with the specified name
+ * in this package (for example, "Object.js"
).
+ * The name has to be a valid javaScript unit name.
+ * This is a handle-only method. The javaScript unit may or may not be present.
+ *
+ * @param name the given name
+ * @return the javaScript unit with the specified name in this package
+ * @see JavaScriptConventions#validateCompilationUnitName(String name, String sourceLevel, String complianceLevel)
+ */
+ IJavaScriptUnit getJavaScriptUnit(String name);
+ /**
+ * Returns all of the javaScript units in this source folder.
+ *
+ *
Note: it is possible that a source folder contains only
+ * read-only files (in other words, its kind is K_BINARY
), in which
+ * case this method returns an empty collection.
+ *
+ * Only existing working copies are returned. So a javaScript unit handle that has no + * corresponding resource on disk will be included if and only if is in working copy mode. + *
+ *Note: it is possible that a source folder contains only
+ * read-only files (in other words, its kind is K_BINARY
), in which
+ * case this method returns an empty collection.
+ *
"java.lang"
, or ""
(the empty string),
+ * for the default package.
+ *
+ * @return the dot-separated package name of this fragment
+ */
+ String getElementName();
+ /**
+ * Returns this package fragment's root kind encoded as an integer.
+ * A package fragment can contain source files (i.e. files with one of
+ * the {@link JavaScriptCore#getJavaScriptLikeExtensions() JavaScript-like extensions}),
+ * or .class
files. This is a convenience method.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return this package fragment's root kind encoded as an integer
+ * @see IPackageFragmentRoot#K_SOURCE
+ * @see IPackageFragmentRoot#K_BINARY
+ */
+ int getKind() throws JavaScriptModelException;
+ /**
+ * Returns an array of non-JavaScript resources contained in this source folder.
+ * + * Non-JavaScript resources includes other files and folders located in the same + * directory as the javaScript units for this package + * fragment. Source files excluded from this package by virtue of + * inclusion/exclusion patterns on the corresponding source includepath entry + * are considered non-JavaScript resources and will appear in the result + * (possibly in a folder). + *
+ * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return an array of non-JavaScript resources (IFile
s,
+ * IFolder
s, or IStorage
s if the
+ * package fragment is in an archive) contained in this package
+ * fragment
+ * @see IIncludePathEntry#getInclusionPatterns()
+ * @see IIncludePathEntry#getExclusionPatterns()
+ */
+ Object[] getNonJavaScriptResources() throws JavaScriptModelException;
+ /**
+ * Returns whether this package fragment's name is
+ * a prefix of other package fragments in this package fragment's
+ * root.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return true if this package fragment's name is a prefix of other package fragments in this package fragment's root, false otherwise
+ */
+ boolean hasSubpackages() throws JavaScriptModelException;
+ /**
+ * Returns whether this package fragment is a default package.
+ * This is a handle-only method.
+ *
+ * @return true if this package fragment is a default package
+ */
+ boolean isDefaultPackage();
+
+ boolean isSource();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IPackageFragmentRoot.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IPackageFragmentRoot.java
new file mode 100644
index 0000000..1679049
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IPackageFragmentRoot.java
@@ -0,0 +1,432 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - specified that a source archive or a source folder can be attached to a binary
+ * package fragment root.
+ * IBM Corporation - added root manipulation APIs: copy, delete, move
+ * IBM Corporation - added DESTINATION_PROJECT_INCLUDEPATH
+ * IBM Corporation - added OTHER_REFERRING_PROJECTS_INCLUDEPATH
+ * IBM Corporation - added NO_RESOURCE_MODIFICATION
+ * IBM Corporation - added REPLACE
+ * IBM Corporation - added ORIGINATING_PROJECT_INCLUDEPATH
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * A package fragment root (or source folder root) contains a set of source folders (package fragments).
+ * It corresponds to an underlying resource which is either folder. All descendant folders represent
+ * package fragments. For a given child folder representing a package fragment,
+ * the corresponding package name is composed of the folder names between the folder
+ * for this root and the child folder representing the package, separated by '.'.
+ * Package fragment roots need to be opened before they can be navigated or manipulated.
+ * The children are of type IPackageFragment
, and are in no particular order.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IPackageFragmentRoot + extends IParent, IJavaScriptElement, IOpenable { + /** + * Kind constant for a source path root. Indicates this root + * only contains source files. + */ + int K_SOURCE = 1; + /** + * Kind constant for a binary path root. Indicates this + * root only contains binary (non-editable) files. + */ + int K_BINARY = 2; + /** + * Empty root path + */ + String DEFAULT_PACKAGEROOT_PATH = ""; //$NON-NLS-1$ + /** + * Update model flag constant (bit mask value 1) indicating that the operation + * is to not copy/move/delete the package fragment root resource. + */ + int NO_RESOURCE_MODIFICATION = 1; + /** + * Update model flag constant (bit mask value 2) indicating that the operation + * is to update the includepath of the originating project. + */ + int ORIGINATING_PROJECT_INCLUDEPATH = 2; + /** + * Update model flag constant (bit mask value 4) indicating that the operation + * is to update the includepath of all referring projects except the originating project. + */ + int OTHER_REFERRING_PROJECTS_INCLUDEPATH = 4; + /** + * Update model flag constant (bit mask value 8) indicating that the operation + * is to update the includepath of the destination project. + */ + int DESTINATION_PROJECT_INCLUDEPATH = 8; + /** + * Update model flag constant (bit mask value 16) indicating that the operation + * is to replace the resource and the destination project's includepath entry. + */ + int REPLACE = 16; + /* + * Attaches the source archive identified by the given absolute path to this + * binary package fragment root.rootPath
specifies the location
+ * of the root within the archive or folder (empty specifies the default root
+ * and null
specifies the root path should be detected).
+ * Once a source archive or folder is attached to the package fragment root,
+ * the getSource
and getSourceRange
+ * methods become operational for binary types/members.
+ * To detach a source archive or folder from a package fragment root, specify
+ * null
as the source path.
+ *
+ * @param sourcePath the given absolute path to the source archive or folder
+ * @param rootPath specifies the location of the root within the archive
+ * (empty specifies the default root and null
specifies
+ * automatic detection of the root path)
+ * @param monitor the given progress monitor
+ * @exception JavaScriptModelException if this operation fails. Reasons include:
+ * CoreException
occurred while updating a server property
+ * IResource.copy(IPath, int, IProgressMonitor)
+ * but excluding nested source folders.
+ *
+ * If NO_RESOURCE_MODIFICATION
is specified in
+ * updateModelFlags
or if this package fragment root is external,
+ * this operation doesn't copy the resource. updateResourceFlags
+ * is then ignored.
+ *
+ * If DESTINATION_PROJECT_INCLUDEPATH
is specified in
+ * updateModelFlags
, updates the includepath of the
+ * destination's project (if it is a JavaScript project). If a non-null
+ * sibling is specified, a copy of this root's includepath entry is inserted before the
+ * sibling on the destination project's raw includepath. If null
is
+ * specified, the includepath entry is added at the end of the raw includepath.
+ *
+ * If REPLACE
is specified in updateModelFlags
,
+ * overwrites the resource at the destination path if any.
+ * If the same includepath entry already exists on the destination project's raw
+ * includepath, then the sibling is ignored and the new includepath entry replaces the
+ * existing one.
+ *
+ * If no flags is specified in updateModelFlags
(using
+ * IResource.NONE
), the default behavior applies: the
+ * resource is copied (if this package fragment root is not external) and the
+ * includepath is not updated.
+ *
IResource.FORCE
and IResource.SHALLOW
)
+ * @param updateModelFlags bit-wise or of update resource flag constants
+ * (DESTINATION_PROJECT_INCLUDEPATH
and
+ * NO_RESOURCE_MODIFICATION
)
+ * @param sibling the includepath entry before which a copy of the includepath
+ * entry should be inserted or null
if the includepath entry should
+ * be inserted at the end
+ * @param monitor a progress monitor
+ *
+ * @exception JavaScriptModelException if this root could not be copied. Reasons
+ * include:
+ * CoreException
occurred while copying the
+ * resource or updating a includepathupdateModelFlags
+ * has been specified as DESTINATION_PROJECT_INCLUDEPATH
+ * (INVALID_DESTINATION)updateModelFlags
+ * has not been specified as REPLACE
force
flag, see IFolder.create
.
+ *
+ * @param name the given dot-separated package name
+ * @param force a flag controlling how to deal with resources that
+ * are not in sync with the local file system
+ * @param monitor the given progress monitor
+ * @exception JavaScriptModelException if the element could not be created. Reasons include:
+ * CoreException
occurred while creating an underlying resource
+ * IResource.delete(int, IProgressMonitor)
but excluding nested
+ * source folders.
+ *
+ * If NO_RESOURCE_MODIFICATION
is specified in
+ * updateModelFlags
or if this package fragment root is external,
+ * this operation doesn't delete the resource. updateResourceFlags
+ * is then ignored.
+ *
+ * If ORIGINATING_PROJECT_INCLUDEPATH
is specified in
+ * updateModelFlags
, update the raw includepath of this package
+ * fragment root's project by removing the corresponding includepath entry.
+ *
+ * If OTHER_REFERRING_PROJECTS_INCLUDEPATH
is specified in
+ * updateModelFlags
, update the raw includepaths of all other JavaScript
+ * projects referring to this root's resource by removing the corresponding includepath
+ * entries.
+ *
+ * If no flags is specified in updateModelFlags
(using
+ * IResource.NONE
), the default behavior applies: the
+ * resource is deleted (if this package fragment root is not external) and no
+ * includepaths are updated.
+ *
IResource.FORCE
and IResource.KEEP_HISTORY
)
+ * @param updateModelFlags bit-wise or of update resource flag constants
+ * (ORIGINATING_PROJECT_INCLUDEPATH
,
+ * OTHER_REFERRING_PROJECTS_INCLUDEPATH
and
+ * NO_RESOURCE_MODIFICATION
)
+ * @param monitor a progress monitor
+ *
+ * @exception JavaScriptModelException if this root could not be deleted. Reasons
+ * include:
+ * CoreException
occurred while deleting the resource
+ * or updating a includepath
+ * .class
files, but not both.
+ * If the underlying folder or archive contains other kinds of files, they are ignored.
+ * In particular, .class
files are ignored under a source package fragment root,
+ * and source files are ignored under a binary package fragment root.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return this package fragment root's kind encoded as an integer
+ * @see IPackageFragmentRoot#K_SOURCE
+ * @see IPackageFragmentRoot#K_BINARY
+ */
+ int getKind() throws JavaScriptModelException;
+
+ /**
+ * Returns an array of non-JavaScript resources contained in this package fragment root.
+ * + * Non-JavaScript resources includes other files and folders located in the same + * directories as the compilation units or class files under this package + * fragment root. Resources excluded from this package fragment root + * by virtue of inclusion/exclusion patterns on the corresponding source includepath + * entry are considered non-JavaScript resources and will appear in the result + * (possibly in a folder). Thus when a nested source folder is excluded, it will appear + * in the non-JavaScript resources of the outer folder. + *
+ * @return an array of non-JavaScript resources (IFile
s,
+ * IFolder
s, or IStorage
s if the
+ * package fragment root is in archive) contained in this package
+ * fragment root
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @see IIncludePathEntry#getInclusionPatterns()
+ * @see IIncludePathEntry#getExclusionPatterns()
+ */
+ Object[] getNonJavaScriptResources() throws JavaScriptModelException;
+
+ /**
+ * Returns the package fragment with the given package name.
+ * An empty string indicates the default package.
+ * This is a handle-only operation. The package fragment
+ * may or may not exist.
+ *
+ * @param packageName the given package name
+ * @return the package fragment with the given package name
+ */
+ IPackageFragment getPackageFragment(String packageName);
+
+
+ /**
+ * Returns the first raw includepath entry that corresponds to this package
+ * fragment root.
+ * A raw includepath entry corresponds to a package fragment root if once resolved
+ * this entry's path is equal to the root's path.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the first raw includepath entry that corresponds to this package fragment root
+ */
+ IIncludePathEntry getRawIncludepathEntry() throws JavaScriptModelException;
+
+ /**
+ * Returns the absolute path to the source archive attached to
+ * this package fragment root's binary archive.
+ *
+ * @return the absolute path to the corresponding source archive,
+ * or null
if this package fragment root's binary archive
+ * has no corresponding source archive, or if this package fragment root
+ * is not a binary archive
+ * @exception JavaScriptModelException if this operation fails
+ */
+ IPath getSourceAttachmentPath() throws JavaScriptModelException;
+
+ /**
+ * Returns the path within this package fragment root's source archive.
+ * An empty path indicates that packages are located at the root of the
+ * source archive.
+ *
+ * @return the path within the corresponding source archive,
+ * or null
if this package fragment root's binary archive
+ * has no corresponding source archive, or if this package fragment root
+ * is not a binary archive
+ * @exception JavaScriptModelException if this operation fails
+ */
+ IPath getSourceAttachmentRootPath() throws JavaScriptModelException;
+
+ /**
+ * Returns whether this package fragment root's underlying
+ * resource is a binary archive (a JAR or zip file).
+ * + * This is a handle-only method. + *
+ * + * @return true if this package fragment root's underlying resource is a binary archive, false otherwise + */ + public boolean isArchive(); + + public boolean isLanguageRuntime(); + /** + * Returns whether this package fragment root is external + * to the workbench (that is, a local file), and has no + * underlying resource. + *+ * This is a handle-only method. + *
+ * + * @return true if this package fragment root is external + * to the workbench (that is, a local file), and has no + * underlying resource, false otherwise + */ + boolean isExternal(); + + /** + * Moves the resource of this package fragment root to the destination path + * as specified byIResource.move(IPath,int,IProgressMonitor)
+ * but excluding nested source folders.
+ *
+ * If NO_RESOURCE_MODIFICATION
is specified in
+ * updateModelFlags
or if this package fragment root is external,
+ * this operation doesn't move the resource. updateResourceFlags
+ * is then ignored.
+ *
+ * If DESTINATION_PROJECT_INCLUDEPATH
is specified in
+ * updateModelFlags
, updates the includepath of the
+ * destination's project (if it is a JavaScript project). If a non-null
+ * sibling is specified, a copy of this root's includepath entry is inserted before the
+ * sibling on the destination project's raw includepath. If null
is
+ * specified, the includepath entry is added at the end of the raw includepath.
+ *
+ * If ORIGINATING_PROJECT_INCLUDEPATH
is specified in
+ * updateModelFlags
, update the raw includepath of this package
+ * fragment root's project by removing the corresponding includepath entry.
+ *
+ * If OTHER_REFERRING_PROJECTS_INCLUDEPATH
is specified in
+ * updateModelFlags
, update the raw includepaths of all other JavaScript
+ * projects referring to this root's resource by removing the corresponding includepath
+ * entries.
+ *
+ * If REPLACE
is specified in updateModelFlags
,
+ * overwrites the resource at the destination path if any.
+ * If the same includepath entry already exists on the destination project's raw
+ * includepath, then the sibling is ignored and the new includepath entry replaces the
+ * existing one.
+ *
+ * If no flags is specified in updateModelFlags
(using
+ * IResource.NONE
), the default behavior applies: the
+ * resource is moved (if this package fragment root is not external) and no
+ * includepaths are updated.
+ *
IResource.FORCE
, IResource.KEEP_HISTORY
+ * and IResource.SHALLOW
)
+ * @param updateModelFlags bit-wise or of update resource flag constants
+ * (DESTINATION_PROJECT_INCLUDEPATH
,
+ * ORIGINATING_PROJECT_INCLUDEPATH
,
+ * OTHER_REFERRING_PROJECTS_INCLUDEPATH
and
+ * NO_RESOURCE_MODIFICATION
)
+ * @param sibling the includepath entry before which a copy of the includepath
+ * entry should be inserted or null
if the includepath entry should
+ * be inserted at the end
+ * @param monitor a progress monitor
+ *
+ * @exception JavaScriptModelException if this root could not be moved. Reasons
+ * include:
+ * CoreException
occurred while copying the
+ * resource or updating a includepathupdateModelFlags
+ * has been specified as DESTINATION_PROJECT_INCLUDEPATH
+ * (INVALID_DESTINATION)updateModelFlags
+ * has not been specified as REPLACE
+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IParent { +/** + * Returns the immediate children of this element. + * Unless otherwise specified by the implementing element, + * the children are in no particular order. + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + * @return the immediate children of this element + */ +IJavaScriptElement[] getChildren() throws JavaScriptModelException; +/** + * Returns whether this element has one or more immediate children. + * This is a convenience method, and may be more efficient than + * testing whethergetChildren
is an empty array.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @return true if the immediate children of this element, false otherwise
+ */
+boolean hasChildren() throws JavaScriptModelException;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IProblemRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IProblemRequestor.java
new file mode 100644
index 0000000..0902752
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IProblemRequestor.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+
+/**
+ * A callback interface for receiving javaScript problem as they are discovered
+ * by some JavaScript operation.
+ *
+ * @see IProblem
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IProblemRequestor {
+
+ /**
+ * Notification of a JavaScript problem.
+ *
+ * @param problem IProblem - The discovered JavaScript problem.
+ */
+ void acceptProblem(IProblem problem);
+
+ /**
+ * Notification sent before starting the problem detection process.
+ * Typically, this would tell a problem collector to clear previously recorded problems.
+ */
+ void beginReporting();
+
+ /**
+ * Notification sent after having completed problem detection process.
+ * Typically, this would tell a problem collector that no more problems should be expected in this
+ * iteration.
+ */
+ void endReporting();
+
+ /**
+ * Predicate allowing the problem requestor to signal whether or not it is currently
+ * interested by problem reports. When answering false
, problem will
+ * not be discovered any more until the next iteration.
+ *
+ * This predicate will be invoked once prior to each problem detection iteration.
+ *
+ * @return boolean - indicates whether the requestor is currently interested by problems.
+ */
+ boolean isActive();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IRegion.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IRegion.java
new file mode 100644
index 0000000..7164652
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IRegion.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+/**
+ * A JavaScript model region describes a hierarchical set of elements.
+ * Regions are often used to describe a set of elements to be considered
+ * when performing operations; for example, the set of elements to be
+ * considered during a search. A region may include elements from different
+ * projects.
+ * + * When an element is included in a region, all of its children + * are considered to be included. Children of an included element + * cannot be selectively excluded. + *
+ *
+ * This interface is not intended to be implemented by clients.
+ * Instances can be created via the JavaScriptCore.newRegion
.
+ *
true
if successful, false
if the remove
+ * fails. If an ancestor of the given element is included, the
+ * remove fails (in other words, it is not possible to selectively
+ * exclude descendants of included ancestors).
+ *
+ * @param element the given element
+ * @return true
if successful, false
if the remove fails
+ */
+ boolean remove(IJavaScriptElement element);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ISourceManipulation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ISourceManipulation.java
new file mode 100644
index 0000000..2a237bd
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ISourceManipulation.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Common protocol for JavaScript elements that support source code manipulations such
+ * as copy, move, rename, and delete.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ISourceManipulation { +/** + * Copies this element to the given container. + * + * @param container the container + * @param sibling the sibling element before which the copy should be inserted, + * ornull
if the copy should be inserted as the last child of
+ * the container
+ * @param rename the new name for the element, or null
if the copy
+ * retains the name of this element
+ * @param replace true
if any existing child in the container with
+ * the target name should be replaced, and false
to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if this element could not be copied. Reasons include:
+ * CoreException
occurred while updating an underlying resource
+ * replace
has been specified as false
+ * null
+ */
+void copy(IJavaScriptElement container, IJavaScriptElement sibling, String rename, boolean replace, IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Deletes this element, forcing if specified and necessary.
+ *
+ * @param force a flag controlling whether underlying resources that are not
+ * in sync with the local file system will be tolerated (same as the force flag
+ * in IResource operations).
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if this element could not be deleted. Reasons include:
+ * CoreException
occurred while updating an underlying resource (CORE_EXCEPTION)null
if the element should be inserted as the last child of
+ * the container
+ * @param rename the new name for the element, or null
if the
+ * element retains its name
+ * @param replace true
if any existing child in the container with
+ * the target name should be replaced, and false
to throw an
+ * exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if this element could not be moved. Reasons include:
+ * CoreException
occurred while updating an underlying resource
+ * replace
has been specified as false
+ * null
+ */
+void move(IJavaScriptElement container, IJavaScriptElement sibling, String rename, boolean replace, IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Renames this element to the given name.
+ *
+ * @param name the new name for the element
+ * @param replace true
if any existing element with the target name
+ * should be replaced, and false
to throw an exception in the
+ * event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaScriptModelException if this element could not be renamed. Reasons include:
+ * CoreException
occurred while updating an underlying resource
+ * replace
has been specified as false
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ISourceRange { + +/** + * Returns the number of characters of the source code for this element, + * relative to the source buffer in which this element is contained. + * + * @return the number of characters of the source code for this element, + * relative to the source buffer in which this element is contained + */ +int getLength(); +/** + * Returns the 0-based index of the first character of the source code for this element, + * relative to the source buffer in which this element is contained. + * + * @return the 0-based index of the first character of the source code for this element, + * relative to the source buffer in which this element is contained + */ +int getOffset(); +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ISourceReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ISourceReference.java new file mode 100644 index 0000000..7f84bad --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ISourceReference.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +/** + * Common protocol for JavaScript elements that have associated source code. + * This set consists ofIClassFile
, IJavaScriptUnit
,
+ * IPackageDeclaration
, IImportDeclaration
,
+ * IImportContainer
, IType
, IField
,
+ * IFunction
, and IInitializer
.
+ * + * Source reference elements may be working copies if they were created from + * a compilation unit that is a working copy. + *
+ *+ * This interface is not intended to be implemented by clients. + *
+ * + * @see IPackageFragmentRoot#attachSource(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor) + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ISourceReference { +/** + * Returns whether this element exists in the model. + * + * @returntrue
if this element exists in the JavaScript model
+ */
+boolean exists();
+
+/**
+ * Returns the source code associated with this element.
+ * This extracts the substring from the source buffer containing this source
+ * element. This corresponds to the source range that would be returned by
+ * getSourceRange
.
+ *
+ * @return the source code, or null
if this element has no
+ * associated source code
+ * @exception JavaScriptModelException if an exception occurs while accessing its corresponding resource
+ */
+String getSource() throws JavaScriptModelException;
+/**
+ * Returns the source range associated with this element.
+ *
+ * @return the source range, or null
if this element has no
+ * associated source code
+ * @exception JavaScriptModelException if an exception occurs while accessing its corresponding resource
+ */
+ISourceRange getSourceRange() throws JavaScriptModelException;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IType.java
new file mode 100644
index 0000000..4cf7706
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/IType.java
@@ -0,0 +1,716 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - added J2SE 1.5 support
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.io.InputStream;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Represents a source type in a JavaScript file (either a top-level
+ * type, a member type, or a local type)
+ *
+ *
+ * The children are of type IMember
, which includes IField
,
+ * IFunction
, IInitializer
and IType
.
+ * The children are listed in the order in which they appear in the source file.
+ *
+ * This interface is not intended to be implemented by clients. + *
+ *+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + *
+ */ +public interface IType extends IMember, IFunctionContainer { + + /** + * Do code completion inside a code snippet in the context of the current type. + * + * If the type can access to his source code and the insertion position is valid, + * then completion is performed against source. Otherwise the completion is performed + * against type structure and given locals variables. + * + * @param snippet the code snippet + * @param insertion the position with in source where the snippet + * is inserted. This position must not be in comments. + * A possible value is -1, if the position is not known. + * @param position the position within snippet where the user + * is performing code assist. + * @param localVariableTypeNames an array (possibly empty) of fully qualified + * type names of local variables visible at the current scope + * @param localVariableNames an array (possibly empty) of local variable names + * that are visible at the current scope + * @param localVariableModifiers an array (possible empty) of modifiers for + * local variables + * @param isStatic whether the current scope is in a static context + * @param requestor the completion requestor + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + void codeComplete( + char[] snippet, + int insertion, + int position, + char[][] localVariableTypeNames, + char[][] localVariableNames, + int[] localVariableModifiers, + boolean isStatic, + CompletionRequestor requestor) + throws JavaScriptModelException; + + /** + * Do code completion inside a code snippet in the context of the current type. + * It considers types in the working copies with the given owner first. In other words, + * the owner's working copies will take precedence over their original compilation units + * in the workspace. + *+ * Note that if a working copy is empty, it will be as if the original compilation + * unit had been deleted. + *
+ * If the type can access to his source code and the insertion position is valid, + * then completion is performed against source. Otherwise the completion is performed + * against type structure and given locals variables. + *
+ * + * @param snippet the code snippet + * @param insertion the position with in source where the snippet + * is inserted. This position must not be in comments. + * A possible value is -1, if the position is not known. + * @param position the position with in snippet where the user + * is performing code assist. + * @param localVariableTypeNames an array (possibly empty) of fully qualified + * type names of local variables visible at the current scope + * @param localVariableNames an array (possibly empty) of local variable names + * that are visible at the current scope + * @param localVariableModifiers an array (possible empty) of modifiers for + * local variables + * @param isStatic whether the current scope is in a static context + * @param requestor the completion requestor + * @param owner the owner of working copies that take precedence over their original compilation units + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + void codeComplete( + char[] snippet, + int insertion, + int position, + char[][] localVariableTypeNames, + char[][] localVariableNames, + int[] localVariableModifiers, + boolean isStatic, + CompletionRequestor requestor, + WorkingCopyOwner owner) + throws JavaScriptModelException; + + + /** + * Creates and returns a field in this type with the + * given contents. + *+ * Optionally, the new element can be positioned before the specified + * sibling. If no sibling is specified, the element will be inserted + * as the last field declaration in this type.
+ * + *It is possible that a field with the same name already exists in this type.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the field is created with the new contentsfalse
- in this case a JavaScriptModelException
is thrownCoreException
occurred while updating an underlying resource
+ * + * Optionally, the new element can be positioned before the specified + * sibling. If no sibling is specified, the element will be appended + * to this type. + * + *
It is possible that a method with the same signature already exists in this type.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the method is created with the new contentsfalse
- in this case a JavaScriptModelException
is thrownCoreException
occurred while updating an underlying resource
+ * + * Optionally, the new type can be positioned before the specified + * sibling. If no sibling is specified, the type will be appended + * to this type.
+ * + *It is possible that a type with the same name already exists in this type.
+ * The value of the force
parameter effects the resolution of
+ * such a conflict:
true
- in this case the type is created with the new contentsfalse
- in this case a JavaScriptModelException
is thrownCoreException
occurred while updating an underlying resource
+ * null
if no such methods can be found.
+ *
+ */
+ IFunction[] findMethods(IFunction method);
+
+ /**
+ * Returns the children of this type that have the given category as a @category
tag.
+ * Returns an empty array if no children with this category exist.
+ *
+ * @return the children for the given category.
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ */
+ IJavaScriptElement[] getChildrenForCategory(String category) throws JavaScriptModelException;
+
+ /**
+ * Returns the simple name of this type, unqualified by package or enclosing type.
+ * This is a handle-only method.
+ *
+ * @return the simple name of this type
+ */
+ String getElementName();
+
+ /**
+ * Returns the field with the specified name
+ * in this type (for example, "bar"
).
+ * This is a handle-only method. The field may or may not exist.
+ *
+ * @param name the given name
+ * @return the field with the specified name in this type
+ */
+ IField getField(String name);
+
+ /**
+ * Returns the fields declared by this type.
+ * If this is a source type, the results are listed in the order
+ * in which they appear in the source, otherwise, the results are
+ * in no particular order. For binary types, this includes synthetic fields.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the fields declared by this type
+ */
+ IField[] getFields() throws JavaScriptModelException;
+
+ /**
+ * Returns the fully qualified name of this type,
+ * including qualification for any containing types and packages.
+ * This is the name of the package, followed by '.'
,
+ * followed by the type-qualified name.
+ * This is a handle-only method.
+ *
+ * @see IType#getTypeQualifiedName()
+ * @return the fully qualified name of this type
+ */
+ String getFullyQualifiedName();
+
+ /**
+ * Returns the fully qualified name of this type,
+ * including qualification for any containing types and packages.
+ * This is the name of the package, followed by '.'
,
+ * followed by the type-qualified name using the enclosingTypeSeparator
.
+ *
+ *
+ * This is a handle-only method.
+ *
+ * @param enclosingTypeSeparator the given enclosing type separator
+ * @return the fully qualified name of this type, including qualification for any containing types and packages
+ * @see IType#getTypeQualifiedName(char)
+ */
+ String getFullyQualifiedName(char enclosingTypeSeparator);
+
+ /**
+ * Returns this type's fully qualified name
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the fully qualified parameterized representation of this type
+ */
+ String getFullyQualifiedParameterizedName() throws JavaScriptModelException;
+
+ /**
+ * Returns the initializer with the specified position relative to
+ * the order they are defined in the source.
+ * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0).
+ * This is a handle-only method. The initializer may or may not be present.
+ *
+ * @param occurrenceCount the specified position
+ * @return the initializer with the specified position relative to the order they are defined in the source
+ */
+ IInitializer getInitializer(int occurrenceCount);
+
+ /**
+ * Returns the initializers declared by this type.
+ * For binary types this is an empty collection.
+ * If this is a source type, the results are listed in the order
+ * in which they appear in the source.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the initializers declared by this type
+ */
+ IInitializer[] getInitializers() throws JavaScriptModelException;
+
+ /**
+ * Returns the binding key for this type. A binding key is a key that uniquely
+ * identifies this type. It allows access to generic info for parameterized
+ * types.
+ *
+ * @return the binding key for this type
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#getKey()
+ * @see BindingKey
+ */
+ String getKey();
+
+ /**
+ * Returns the method with the specified name and parameter types
+ * in this type (for example, "foo", {"I", "QString;"}
).
+ * To get the handle for a constructor, the name specified must be the
+ * simple name of the enclosing type.
+ * This is a handle-only method. The method may or may not be present.
+ * + * The type signatures may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @param name the given name + * @param parameterTypeSignatures the given parameter types + * @return the method with the specified name and parameter types in this type + */ + IFunction getFunction(String name, String[] parameterTypeSignatures); + + /** + * Returns the methods and constructors declared by this type. + * For binary types, this may include the special<clinit>
; method
+ * and synthetic methods.
+ * If this is a source type, the results are listed in the order
+ * in which they appear in the source, otherwise, the results are
+ * in no particular order.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the methods and constructors declared by this type
+ */
+ IFunction[] getFunctions() throws JavaScriptModelException;
+
+ /**
+ * Returns the source folder (package fragment) in which this element is defined.
+ * This is a handle-only method.
+ *
+ * @return the package fragment in which this element is defined
+ */
+ IPackageFragment getPackageFragment();
+
+ /**
+ * Returns the name of this type's superclass, or null
+ * for source types that do not specify a superclass.
+ *
+ * For interfaces, the superclass name is always "java.lang.Object"
.
+ * For source types, the name as declared is returned, for binary types,
+ * the resolved, qualified name is returned.
+ * For anonymous types, the superclass name is the name appearing after the 'new' keyword'.
+ * If the superclass is a parameterized type, the string
+ * may include its type arguments enclosed in "<>".
+ * If the returned string is needed for anything other than display
+ * purposes, use {@link #getSuperclassTypeSignature()} which returns
+ * a structured type signature string containing more precise information.
+ *
null
for source types that do not specify a superclass
+ */
+ String getSuperclassName() throws JavaScriptModelException;
+
+ /**
+ * Returns the type signature of this type's superclass, or
+ * null
if none.
+ * + * The type signature may be either unresolved (for source types) + * or resolved (for binary types), and either basic (for basic types) + * or rich (for parameterized types). See {@link Signature} for details. + *
+ * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return the type signature of this type's superclass, or + *null
if none
+ */
+ String getSuperclassTypeSignature() throws JavaScriptModelException;
+
+ /**
+ * Returns the member type declared in this type with the given simple name.
+ * This is a handle-only method. The type may or may not exist.
+ *
+ * @param name the given simple name
+ * @return the member type declared in this type with the given simple name
+ */
+ IType getType(String name);
+
+ /**
+ * Returns the type-qualified name of this type,
+ * including qualification for any enclosing types,
+ * but not including package qualification.
+ * This is a handle-only method.
+ *
+ * @return the type-qualified name of this type
+ */
+ String getTypeQualifiedName();
+
+ /**
+ * Returns the type-qualified name of this type,
+ * including qualification for any enclosing types,
+ * but not including package qualification.
+ *
+ * This is a handle-only method.
+ *
+ * @param enclosingTypeSeparator the specified enclosing type separator
+ * @return the type-qualified name of this type
+ */
+ String getTypeQualifiedName(char enclosingTypeSeparator);
+
+ /**
+ * Returns the immediate member types declared by this type.
+ * The results are listed in the order in which they appear in the source or class file.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return the immediate member types declared by this type
+ */
+ IType[] getTypes() throws JavaScriptModelException;
+
+ /**
+ * Returns whether this type represents an anonymous type.
+ *
+ * @exception JavaScriptModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return true if this type represents an anonymous type, false otherwise
+ */
+ boolean isAnonymous() throws JavaScriptModelException;
+
+ /**
+ * Returns whether this type is read-only.
+ * + * Note that a class can neither be an interface, an enumeration class, nor an annotation type. + *
+ * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return true if this type represents a class, false otherwise + */ + boolean isClass() throws JavaScriptModelException; + + /** + * Returns whether this type represents a local type. + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return true if this type represents a local type, false otherwise + */ + boolean isLocal() throws JavaScriptModelException; + + /** + * Returns whether this type represents a member type. + * + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return true if this type represents a member type, false otherwise + */ + boolean isMember() throws JavaScriptModelException; + /** + * Returns whether this type represents a resolved type. + * If a type is resolved, its key contains resolved information. + * + * @return whether this type represents a resolved type. + */ + boolean isResolved(); + /** + * Loads a previously saved ITypeHierarchy from an input stream. A type hierarchy can + * be stored using ITypeHierachy#store(OutputStream). + * + * Only hierarchies originally created by the following methods can be loaded: + *+ * Note that passing an empty working copy will be as if the original compilation + * unit had been deleted. + *
+ * + * @param workingCopies the working copies that take precedence over their original compilation units + * @param monitor the given progress monitor + * @return a type hierarchy for this type containing this type and all of its supertypes + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + ITypeHierarchy newSupertypeHierarchy(IJavaScriptUnit[] workingCopies, IProgressMonitor monitor) + throws JavaScriptModelException; + + /** + * Creates and returns a type hierarchy for this type containing + * this type and all of its supertypes, considering types in the + * working copies with the given owner. + * In other words, the owner's working copies will take + * precedence over their original compilation units in the workspace. + *+ * Note that if a working copy is empty, it will be as if the original compilation + * unit had been deleted. + *
+ * + * @param owner the owner of working copies that take precedence over their original compilation units + * @param monitor the given progress monitor + * @return a type hierarchy for this type containing this type and all of its supertypes + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + ITypeHierarchy newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor) + throws JavaScriptModelException; + + /** + * Creates and returns a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes + * in the context of the given project. + * + * @param project the given project + * @param monitor the given progress monitor + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes + * in the context of the given project + */ + ITypeHierarchy newTypeHierarchy(IJavaScriptProject project, IProgressMonitor monitor) throws JavaScriptModelException; + + /** + * Creates and returns a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes + * in the context of the given project, considering types in the + * working copies with the given owner. + * In other words, the owner's working copies will take + * precedence over their original compilation units in the workspace. + *
+ * Note that if a working copy is empty, it will be as if the original compilation + * unit had been deleted. + *
+ * + * @param project the given project + * @param owner the owner of working copies that take precedence over their original compilation units + * @param monitor the given progress monitor + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes + * in the context of the given project + */ + ITypeHierarchy newTypeHierarchy(IJavaScriptProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaScriptModelException; + + /** + * Creates and returns a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes in the workspace. + * + * @param monitor the given progress monitor + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @return a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes in the workspace + */ + ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws JavaScriptModelException; + + /** + * Creates and returns a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes in the workspace, + * considering types in the given working copies. In other words, the list of working + * copies that will take precedence over their original compilation units in the workspace. + *
+ * Note that passing an empty working copy will be as if the original compilation + * unit had been deleted. + * + * @param workingCopies the working copies that take precedence over their original compilation units + * @param monitor the given progress monitor + * @return a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes in the workspace + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + ITypeHierarchy newTypeHierarchy(IJavaScriptUnit[] workingCopies, IProgressMonitor monitor) throws JavaScriptModelException; + + /** + * Creates and returns a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes in the workspace, + * considering types in the working copies with the given owner. + * In other words, the owner's working copies will take + * precedence over their original compilation units in the workspace. + *
+ * Note that if a working copy is empty, it will be as if the original compilation + * unit had been deleted. + *
+ * + * @param owner the owner of working copies that take precedence over their original compilation units + * @param monitor the given progress monitor + * @return a type hierarchy for this type containing + * this type, all of its supertypes, and all its subtypes in the workspace + * @exception JavaScriptModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + ITypeHierarchy newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaScriptModelException; + + /** + * Resolves the given type name within the context of this type (depending on the type hierarchy + * and its imports). + *
+ * Multiple answers might be found in case there are ambiguous matches. + *
+ *+ * Each matching type name is decomposed as an array of two strings, the first denoting the package + * name (dot-separated) and the second being the type name. The package name is empty if it is the + * default package. The type name is the type qualified name using a '.' enclosing type separator. + *
+ *
+ * Returns null
if unable to find any matching type.
+ *
null
if unable to find any matching type
+ * @see #getTypeQualifiedName(char)
+ */
+ String[][] resolveType(String typeName) throws JavaScriptModelException;
+
+ /**
+ * Resolves the given type name within the context of this type (depending on the type hierarchy
+ * and its imports) and using the given owner's working copies, considering types in the
+ * working copies with the given owner. In other words, the owner's working copies will take
+ * precedence over their original compilation units in the workspace.
+ * + * Note that if a working copy is empty, it will be as if the original compilation + * unit had been deleted. + *
+ *Multiple answers might be found in case there are ambiguous matches. + *
+ *+ * Each matching type name is decomposed as an array of two strings, the first denoting the package + * name (dot-separated) and the second being the type name. The package name is empty if it is the + * default package. The type name is the type qualified name using a '.' enclosing type separator. + *
+ *
+ * Returns null
if unable to find any matching type.
+ *
null
if unable to find any matching type
+ * @see #getTypeQualifiedName(char)
+ */
+ String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaScriptModelException;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ITypeHierarchy.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ITypeHierarchy.java
new file mode 100644
index 0000000..9706826
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ITypeHierarchy.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.io.OutputStream;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * A type hierarchy provides navigations between a type and its resolved
+ * supertypes and subtypes for a specific type or for all types within a region.
+ * Supertypes may extend outside of the type hierarchy's region in which it was
+ * created such that the root of the hierarchy is always included.
+ *
+ * A type hierarchy is static and can become stale. Although consistent when
+ * created, it does not automatically track changes in the model.
+ * As changes in the model potentially invalidate the hierarchy, change notifications
+ * are sent to registered ITypeHierarchyChangedListener
s. Listeners should
+ * use the exists
method to determine if the hierarchy has become completely
+ * invalid (for example, when the type or project the hierarchy was created on
+ * has been removed). To refresh a hierarchy, use the refresh
method.
+ *
+ * The type hierarchy may contain cycles due to malformed supertype declarations.
+ * Most type hierarchy queries are oblivious to cycles; the getAll*
+ * methods are implemented such that they are unaffected by cycles.
+ *
+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ITypeHierarchy { +/** + * Adds the given listener for changes to this type hierarchy. Listeners are + * notified when this type hierarchy changes and needs to be refreshed. + * Has no effect if an identical listener is already registered. + * + * @param listener the listener + */ +void addTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener); +/** + * Returns whether the given type is part of this hierarchy. + * + * @param type the given type + * @return true if the given type is part of this hierarchy, false otherwise + */ +boolean contains(IType type); +/** + * Returns whether the type and project this hierarchy was created on exist. + * @return true if the type and project this hierarchy was created on exist, false otherwise + */ +boolean exists(); +/** + * Returns all classes in this type hierarchy's graph, in no particular + * order. Any classes in the creation region which were not resolved to + * have any subtypes or supertypes are not included in the result. + * + * @return all classes in this type hierarchy's graph + */ +IType[] getAllClasses(); +/** + * Returns all resolved subtypes (direct and indirect) of the + * given type, in no particular order, limited to the + * types in this type hierarchy's graph. An empty array + * is returned if there are no resolved subtypes for the + * given type. + * + * @param type the given type + * @return all resolved subtypes (direct and indirect) of the given type + */ +IType[] getAllSubtypes(IType type); +/** + * Returns all resolved superclasses of the + * given class, in bottom-up order. An empty array + * is returned if there are no resolved superclasses for the + * given class. + * + *NOTE: once a type hierarchy has been created, it is more efficient to
+ * query the hierarchy for superclasses than to query a class recursively up
+ * the superclass chain. Querying an element performs a dynamic resolution,
+ * whereas the hierarchy returns a pre-computed result.
+ *
+ * @param type the given type
+ * @return all resolved superclasses of the given class, in bottom-up order, an empty
+ * array if none.
+ */
+IType[] getAllSuperclasses(IType type);
+/**
+ * Return the flags associated with the given type (would be equivalent to IMember.getFlags()
),
+ * or -1
if this information wasn't cached on the hierarchy during its computation.
+ *
+ * @param type the given type
+ * @return the modifier flags for this member
+ * @see Flags
+ */
+int getCachedFlags(IType type);
+/**
+ * Returns all classes in the graph which have no resolved superclass,
+ * in no particular order.
+ *
+ * @return all classes in the graph which have no resolved superclass
+ */
+IType[] getRootClasses();
+/**
+ * Returns the direct resolved subclasses of the given class,
+ * in no particular order, limited to the classes in this
+ * type hierarchy's graph.
+ * Returns an empty collection if no classes were resolved to be subclasses of the given
+ * class.
+ *
+ * @param type the given type
+ * @return the direct resolved subclasses of the given class limited to the classes in this
+ * type hierarchy's graph, an empty collection if none.
+ */
+IType[] getSubclasses(IType type);
+/**
+ * Returns the resolved superclass of the given class,
+ * or null
if the given class has no superclass or
+ * the superclass could not be resolved.
+ *
+ * @param type the given type
+ * @return the resolved superclass of the given class,
+ * or null
if the given class has no superclass or
+ * the superclass could not be resolved.
+ */
+IType getSuperclass(IType type);
+/**
+ * Returns the type this hierarchy was computed for.
+ * Returns null
if this hierarchy was computed for a region.
+ *
+ * @return the type this hierarchy was computed for
+ */
+IType getType();
+/**
+ * Re-computes the type hierarchy reporting progress.
+ *
+ * @param monitor the given progress monitor
+ * @exception JavaScriptModelException if unable to refresh the hierarchy
+ */
+void refresh(IProgressMonitor monitor) throws JavaScriptModelException;
+/**
+ * Removes the given listener from this type hierarchy.
+ * Has no affect if an identical listener is not registered.
+ *
+ * @param listener the listener
+ */
+void removeTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener);
+/**
+ * Stores the type hierarchy in an output stream. This stored hierarchy can be load by
+ * IType#loadTypeHierachy(IJavaScriptProject, InputStream, IProgressMonitor).
+ * Listeners of this hierarchy are not stored.
+ *
+ * Only hierarchies created by the following methods can be store:
+ *
+ * This interface may be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ITypeHierarchyChangedListener { + /** + * Notifies that the given type hierarchy has changed in some way and should + * be refreshed at some point to make it consistent with the current state of + * the JavaScript model. + * + * @param typeHierarchy the given type hierarchy + */ + void typeHierarchyChanged(ITypeHierarchy typeHierarchy); +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ITypeRoot.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ITypeRoot.java new file mode 100644 index 0000000..01a99be --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ITypeRoot.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import org.eclipse.core.runtime.IProgressMonitor; + + +/** + * Represents an entire JavaScript type root (either anIJavaScriptUnit
+ * or an IClassFile
).
+ *
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * @see IJavaScriptUnit Note that methods {@link #findPrimaryType()} and {@link #getElementAt(int)} + * were already implemented in this interface respectively since version 3.0 and version 1.0. + * @see IClassFile Note that method {@link #getWorkingCopy(WorkingCopyOwner, IProgressMonitor)} + * was already implemented in this interface since version 3.0. + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ITypeRoot extends IJavaScriptElement, IParent, IOpenable, ISourceReference, ICodeAssist, IFunctionContainer { + +/** + * Finds the primary type of this JavaScript type root (that is, the type with the same name as the + * javascript file), ornull
if no such a type exists.
+ *
+ * @return the found primary type of this JavaScript type root, or null
if no such a type exists
+ */
+IType findPrimaryType();
+
+/**
+ * Returns the smallest element within this JavaScript type root that
+ * includes the given source position (that is, a method, field, etc.), or
+ * null
if there is no element other than the JavaScript type root
+ * itself at the given position, or if the given position is not
+ * within the source range of the source of this JavaScript type root.
+ *
+ * @param position a source position inside the JavaScript type root
+ * @return the innermost JavaScript element enclosing a given source position or null
+ * if none (excluding the JavaScript type root).
+ * @throws JavaScriptModelException if the JavaScript type root does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+IJavaScriptElement getElementAt(int position) throws JavaScriptModelException;
+
+/**
+ * Returns a shared working copy on this javaScirpt file using the given working copy owner to create
+ * the buffer. If this is already a working copy of the given owner, the element itself is returned.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original JavaScript type root AND was using the same working copy owner (that is, as defined by {@link Object#equals}).
+ * + * The life time of a shared working copy is as follows: + *
+ * Note that the working copy owner will be used for the life time of the shared working copy, that is if the + * working copy is closed then reopened, this owner will be used. + * The buffer will be automatically initialized with the original's JavaScript type root content upon creation. + *
+ * When the shared working copy instance is created, an ADDED IJavaScriptElementDelta is reported on this + * working copy. + *
+ * A working copy can be created on a not-yet existing compilation unit. + * In particular, such a working copy can then be committed in order to create + * the corresponding compilation unit. + *
+ * Note that possible problems of this working copy are reported using this method. only + * if the given working copy owner returns a problem requestor for this working copy + * (see {@link WorkingCopyOwner#getProblemRequestor(IJavaScriptUnit)}). + *
+ * + * @param owner the working copy owner that creates a buffer that is used to get the content + * of the working copy + * @param monitor a progress monitor used to report progress while opening this compilation unit + * ornull
if no progress should be reported
+ * @throws JavaScriptModelException if the contents of this element can
+ * not be determined.
+ * @return a new working copy of this JavaScript type root using the given owner to create
+ * the buffer, or this JavaScript type root if it is already a working copy
+ */
+IJavaScriptUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaScriptModelException;
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JSDScopeUtil.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JSDScopeUtil.java
new file mode 100644
index 0000000..9fc632e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JSDScopeUtil.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/**
+ *
+ */
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.jsdt.internal.core.ClassFile;
+
+/**
+ * (mostly) static methods to figure out includepath entries and container initializers *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+
+public class JSDScopeUtil {
+
+
+
+
+
+ public static JsGlobalScopeContainerInitializer getContainerInitializer(IPath classPathEntry) {
+ if(classPathEntry==null ) return null;
+ JsGlobalScopeContainerInitializer initializer= JavaScriptCore.getJsGlobalScopeContainerInitializer(classPathEntry.segment(0));
+ return initializer ;
+ }
+
+ public IIncludePathEntry[] getIncludepathEntries(IJsGlobalScopeContainer container) {
+
+
+ if(container!=null) return container.getIncludepathEntries();
+
+ return new IIncludePathEntry[0];
+ }
+
+ public IJsGlobalScopeContainer getLibraryContainer(IPath cpEntry, IJavaScriptProject javaProject) {
+ IJsGlobalScopeContainer container=null;
+ try {
+ container = JavaScriptCore.getJsGlobalScopeContainer(cpEntry, javaProject);
+ } catch (JavaScriptModelException ex) {
+ // TODO Auto-generated catch block
+ ex.printStackTrace();
+ }
+ return container;
+ }
+
+ public static JsGlobalScopeContainerInitializer findLibraryInitializer(IPath compUnitPath, IJavaScriptProject javaProject) {
+ IPackageFragmentRoot[] roots = new IPackageFragmentRoot[0];
+ try {
+ roots = javaProject.getAllPackageFragmentRoots();
+ } catch (JavaScriptModelException ex) {
+ // TODO Auto-generated catch block
+ ex.printStackTrace();
+ }
+ for (int i = 0;inull
if the id was not valid
+ */
+ private static synchronized char[] scannedIdentifier(String id, String sourceLevel, String complianceLevel) {
+ if (id == null) {
+ return null;
+ }
+ // Set scanner for given source and compliance levels
+ SCANNER.sourceLevel = sourceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(sourceLevel);
+ SCANNER.complianceLevel = complianceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(complianceLevel);
+
+ try {
+ SCANNER.setSource(id.toCharArray());
+ int token = SCANNER.scanIdentifier();
+ if (token != TerminalTokens.TokenNameIdentifier) return null;
+ if (SCANNER.currentPosition == SCANNER.eofPosition) { // to handle case where we had an ArrayIndexOutOfBoundsException
+ try {
+ return SCANNER.getCurrentIdentifierSource();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+ catch (InvalidInputException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Validate the given javaScript unit name.
+ * + * A javaScript unit name must obey the following rules: + *
IStatus.OK
if
+ * the given name is valid as a javaScript unit name, otherwise a status
+ * object indicating what is wrong with the name
+ * @deprecated Use {@link #validateCompilationUnitName(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validateCompilationUnitName(String name) {
+ return validateCompilationUnitName(name,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given javaScript unit name for the given source and compliance levels.
+ * + * A javaScript unit name must obey the following rules: + *
IStatus.OK
if
+ * the given name is valid as a javaScript unit name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validateCompilationUnitName(String name, String sourceLevel, String complianceLevel) {
+ if (name == null) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_unit_nullName, null);
+ }
+ if (!org.eclipse.wst.jsdt.internal.core.util.Util.isJavaLikeFileName(name)) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_unit_notJavaName, null);
+ }
+// String identifier;
+ int index;
+ index = name.lastIndexOf('.');
+ if (index == -1) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_unit_notJavaName, null);
+ }
+// identifier = name.substring(0, index);
+ // JSR-175 metadata strongly recommends "package-info.js" as the
+ // file in which to store package annotations and
+ // the package-level spec (replaces package.html)
+// if (!identifier.equals(PACKAGE_INFO)) {
+// IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
+// if (!status.isOK()) {
+// return status;
+// }
+// }
+// IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
+// if (!status.isOK()) {
+// return status;
+// }
+ return JavaModelStatus.VERIFIED_OK;
+ }
+
+ /*
+ * Validate the given .class file name for the given source and compliance levels.
+ * + * A .class file name must obey the following rules: + *
".class"
suffix
+ * IStatus.OK
if
+ * the given name is valid as a .class file name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validateClassFileName(String name, String sourceLevel, String complianceLevel) {
+ if (name == null) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_classFile_nullName, null); }
+ if (!org.eclipse.wst.jsdt.internal.compiler.util.Util.isClassFileName(name)) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_classFile_notClassFileName, null);
+ }
+// String identifier;
+ int index;
+ index = name.lastIndexOf('.');
+ if (index == -1) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_classFile_notClassFileName, null);
+ }
+// identifier = name.substring(0, index);
+ // JSR-175 metadata strongly recommends "package-info.js" as the
+ // file in which to store package annotations and
+ // the package-level spec (replaces package.html)
+// if (!identifier.equals(PACKAGE_INFO)) {
+// IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
+// if (!status.isOK()) {
+// return status;
+// }
+// }
+ IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
+ if (!status.isOK()) {
+ return status;
+ }
+ return JavaModelStatus.VERIFIED_OK;
+ }
+
+ /**
+ * Validate the given var or field name.
+ *
+ * Syntax of a field name corresponds to VariableDeclaratorId (JLS2 8.3).
+ * For example, "x"
.
+ *
+ * @param name the name of a field
+ * @return a status object with code IStatus.OK
if
+ * the given name is valid as a field name, otherwise a status
+ * object indicating what is wrong with the name
+ * @deprecated Use {@link #validateFieldName(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validateFieldName(String name) {
+ return validateIdentifier(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given var or field name for the given source and compliance levels.
+ *
+ * Syntax of a field name corresponds to VariableDeclaratorId (JLS2 8.3).
+ * For example, "x"
.
+ *
+ * @param name the name of a field
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code IStatus.OK
if
+ * the given name is valid as a field name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validateFieldName(String name, String sourceLevel, String complianceLevel) {
+ return validateIdentifier(name, sourceLevel, complianceLevel);
+ }
+
+ /**
+ * Validate the given JavaScript identifier.
+ * The identifier must not have the same spelling as a JavaScript keyword,
+ * boolean literal ("true"
, "false"
), or null literal ("null"
).
+ * A valid identifier can act as a simple type name, method name or field name.
+ *
+ * @param id the JavaScript identifier
+ * @return a status object with code IStatus.OK
if
+ * the given identifier is a valid JavaScript identifier, otherwise a status
+ * object indicating what is wrong with the identifier
+ * @deprecated Use {@link #validateIdentifier(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validateIdentifier(String id) {
+ return validateIdentifier(id,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given JavaScript identifier for the given source and compliance levels
+ * The identifier must not have the same spelling as a JavaScript keyword,
+ * boolean literal ("true"
, "false"
), or null literal ("null"
).
+ * A valid identifier can act as a simple type name, method name or field name.
+ *
+ * @param id the JavaScript identifier
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code IStatus.OK
if
+ * the given identifier is a valid JavaScript identifier, otherwise a status
+ * object indicating what is wrong with the identifier
+ */
+ public static IStatus validateIdentifier(String id, String sourceLevel, String complianceLevel) {
+ if (scannedIdentifier(id, sourceLevel, complianceLevel) != null) {
+ return JavaModelStatus.VERIFIED_OK;
+ } else {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_illegalIdentifier, id), null);
+ }
+ }
+
+ /**
+ * Validate the given import declaration name for the given source and compliance levels.
+ *
+ * The name of an import corresponds to a fully qualified type name. + * + *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the import declaration + * @param sourceLevel the source level + * @param complianceLevel the compliance level + * @return a status object with codeIStatus.OK
if
+ * the given name is valid as an import declaration, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validateImportDeclaration(String name, String sourceLevel, String complianceLevel) {
+ if (name == null || name.length() == 0) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_import_nullImport, null);
+ }
+ if (name.charAt(name.length() - 1) == '*') {
+ if (name.charAt(name.length() - 2) == '.') {
+ return validatePackageName(name.substring(0, name.length() - 2), sourceLevel, complianceLevel);
+ } else {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_import_unqualifiedImport, null);
+ }
+ }
+ return validatePackageName(name, sourceLevel, complianceLevel);
+ }
+
+ /**
+ * Validate the given JavaScript type name, either simple or qualified.
+ *
+ *
+ * @param name the name of a type
+ * @return a status object with code IStatus.OK
if
+ * the given name is valid as a JavaScript type name,
+ * a status with code IStatus.WARNING
+ * indicating why the given name is discouraged,
+ * otherwise a status object indicating what is wrong with
+ * the name
+ * @deprecated Use {@link #validateJavaScriptTypeName(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validateJavaScriptTypeName(String name) {
+ return validateJavaScriptTypeName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given JavaScript type name, either simple or qualified, for the given source and compliance levels.
+ *
+ *
+ * @param name the name of a type
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code IStatus.OK
if
+ * the given name is valid as a JavaScript type name,
+ * a status with code IStatus.WARNING
+ * indicating why the given name is discouraged,
+ * otherwise a status object indicating what is wrong with
+ * the name
+ */
+ public static IStatus validateJavaScriptTypeName(String name, String sourceLevel, String complianceLevel) {
+ if (name == null) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null);
+ }
+ String trimmed = name.trim();
+ if (!name.equals(trimmed)) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_type_nameWithBlanks, null);
+ }
+ int index = name.lastIndexOf('.');
+ char[] scannedID;
+ if (index == -1) {
+ // simple name
+ scannedID = scannedIdentifier(name, sourceLevel, complianceLevel);
+ } else {
+ // qualified name
+ String pkg = name.substring(0, index).trim();
+ IStatus status = validatePackageName(pkg, sourceLevel, complianceLevel);
+ if (!status.isOK()) {
+ return status;
+ }
+ String type = name.substring(index + 1).trim();
+ scannedID = scannedIdentifier(type, sourceLevel, complianceLevel);
+ }
+
+ if (scannedID != null) {
+ IStatus status = ResourcesPlugin.getWorkspace().validateName(new String(scannedID), IResource.FILE);
+ if (!status.isOK()) {
+ return status;
+ }
+ if (CharOperation.contains('$', scannedID)) {
+ return new Status(IStatus.WARNING, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_type_dollarName, null);
+ }
+ if ((scannedID.length > 0 && ScannerHelper.isLowerCase(scannedID[0]))) {
+ return new Status(IStatus.WARNING, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_type_lowercaseName, null);
+ }
+ return JavaModelStatus.VERIFIED_OK;
+ } else {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_type_invalidName, name), null);
+ }
+ }
+
+ /**
+ * Validate the given function name.
+ *
+ *
+ * @param name the name of a method
+ * @return a status object with code IStatus.OK
if
+ * the given name is valid as a method name, otherwise a status
+ * object indicating what is wrong with the name
+ * @deprecated Use {@link #validateFunctionName(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validateFunctionName(String name) {
+ return validateFunctionName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+
+ /**
+ * Validate the given function name for the given source and compliance levels.
+ *
+ *
+ * @param name the name of a method
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code IStatus.OK
if
+ * the given name is valid as a method name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validateFunctionName(String name, String sourceLevel, String complianceLevel) {
+ return validateIdentifier(name, sourceLevel,complianceLevel);
+ }
+
+ /**
+ * Validate the given package name.
+ *
+ * The syntax of a package name corresponds to PackageName as + * defined by PackageDeclaration. + *
+ * Note that the given name must be a non-empty package name (that is, attempting to + * validate the default package will return an error status.) + * Also it must not contain any characters or substrings that are not valid + * on the file system on which workspace root is located. + * + *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of a package + * @return a status object with codeIStatus.OK
if
+ * the given name is valid as a package name, otherwise a status
+ * object indicating what is wrong with the name
+ * @deprecated Use {@link #validatePackageName(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validatePackageName(String name) {
+ return validatePackageName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given package name for the given source and compliance levels.
+ * + * The syntax of a package name corresponds to PackageName as + * defined by PackageDeclaration. + *
+ * Note that the given name must be a non-empty package name (that is, attempting to + * validate the default package will return an error status.) + * Also it must not contain any characters or substrings that are not valid + * on the file system on which workspace root is located. + * + *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of a package + * @param sourceLevel the source level + * @param complianceLevel the compliance level + * @return a status object with codeIStatus.OK
if
+ * the given name is valid as a package name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validatePackageName(String name, String sourceLevel, String complianceLevel) {
+
+ if (name == null) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_nullName, null);
+ }
+ int length;
+ if ((length = name.length()) == 0) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_emptyName, null);
+ }
+ if (name.charAt(0) == DOT || name.charAt(length-1) == DOT) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_dotName, null);
+ }
+ if (CharOperation.isWhitespace(name.charAt(0)) || CharOperation.isWhitespace(name.charAt(name.length() - 1))) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_nameWithBlanks, null);
+ }
+ int dot = 0;
+ while (dot != -1 && dot < length-1) {
+ if ((dot = name.indexOf(DOT, dot+1)) != -1 && dot < length-1 && name.charAt(dot+1) == DOT) {
+ return new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_consecutiveDotsName, null);
+ }
+ }
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IStatus status = workspace.validateName(new String(name), IResource.FOLDER);
+ if (!status.isOK()) {
+ return status;
+ }
+ StringTokenizer st = new StringTokenizer(name, "."); //$NON-NLS-1$
+ boolean firstToken = true;
+ IStatus warningStatus = null;
+ while (st.hasMoreTokens()) {
+ String typeName = st.nextToken();
+ typeName = typeName.trim(); // grammar allows spaces
+ char[] scannedID = scannedIdentifier(typeName, sourceLevel, complianceLevel);
+ if (scannedID == null) {
+ return new Status(IStatus.WARNING, JavaScriptCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_illegalIdentifier, typeName), null);
+ }
+ status = workspace.validateName(new String(name), IResource.FOLDER);
+ if (!status.isOK()) {
+ return status;
+ }
+ if (firstToken && scannedID.length > 0 && ScannerHelper.isUpperCase(scannedID[0])) {
+ if (warningStatus == null) {
+ warningStatus = new Status(IStatus.WARNING, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_uppercaseName, null);
+ }
+ }
+ firstToken = false;
+ }
+ if (warningStatus != null) {
+ return warningStatus;
+ }
+ return JavaModelStatus.VERIFIED_OK;
+ }
+
+ /**
+ * Validate a given includepath location for a project, using the following rules:
+ * + * This validation is intended to anticipate includepath issues prior to assigning it to a project. In particular, it will automatically + * be performed during the includepath setting operation (if validation fails, the includepath setting will not complete). + *
+ * @param javaProject the given javaScript project
+ * @param rawClasspath the given includepath
+ * @return a status object with code IStatus.OK
if
+ * the given includepath are compatible, otherwise a status
+ * object indicating what is wrong with the includepath
+ */
+ public static IJavaScriptModelStatus validateClasspath(IJavaScriptProject javaProject, IIncludePathEntry[] rawClasspath) {
+
+ return ClasspathEntry.validateClasspath(javaProject, rawClasspath);
+ }
+
+ /**
+ * Returns a JavaScript model status describing the problem related to this includepath entry if any,
+ * a status object with code IStatus.OK
if the entry is fine (that is, if the
+ * given includepath entry denotes a valid element to be referenced onto a includepath).
+ *
+ * @param project the given javaScript project
+ * @param entry the given includepath entry
+ * @param checkSourceAttachment a flag to determine if source attachement should be checked
+ * @return a javaScript model status describing the problem related to this includepath entry if any, a status object with code IStatus.OK
if the entry is fine
+ */
+ public static IJavaScriptModelStatus validateClasspathEntry(IJavaScriptProject project, IIncludePathEntry entry, boolean checkSourceAttachment){
+ IJavaScriptModelStatus status = ClasspathEntry.validateClasspathEntry(project, entry, checkSourceAttachment, true/*recurse in container*/);
+ if (status.getCode() == IJavaScriptModelStatusConstants.INVALID_INCLUDEPATH && ((ClasspathEntry) entry).isOptional())
+ return JavaModelStatus.VERIFIED_OK;
+ return status;
+ }
+
+ /**
+ * Validate the given type variable name.
+ *
+ * + *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of a type variable + * @return a status object with codeIStatus.OK
if
+ * the given name is valid as a type variable name, otherwise a status
+ * object indicating what is wrong with the name
+ * @deprecated Use {@link #validateTypeVariableName(String id, String sourceLevel, String complianceLevel)} instead
+ */
+ public static IStatus validateTypeVariableName(String name) {
+ return validateIdentifier(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given type variable name for the given source and compliance levels.
+ * + *
Note: This Method only applies to ECMAScript 4 which is not yet supported
+ * + * @param name the name of a type variable + * @param sourceLevel the source level + * @param complianceLevel the compliance level + * @return a status object with codeIStatus.OK
if
+ * the given name is valid as a type variable name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static IStatus validateTypeVariableName(String name, String sourceLevel, String complianceLevel) {
+ return validateIdentifier(name, sourceLevel, complianceLevel);
+ }
+
+ /*
+ * Validate that all compiler options of the given project match keys and values
+ * described in {@link JavaScriptCore#getDefaultOptions()} method.
+ *
+ * @param javaProject the given javaScript project
+ * @param inheritJavaCoreOptions inherit project options from JavaScriptCore or not.
+ * @return a status object with code IStatus.OK
if all project
+ * compiler options are valid, otherwise a status object indicating what is wrong
+ * with the keys and their value.
+ */
+ /*
+ public static IStatus validateCompilerOptions(IJavaScriptProject javaProject, boolean inheritJavaCoreOptions) {
+ return validateCompilerOptions(javaProject.getOptions(inheritJavaCoreOptions));
+ }
+ */
+
+ /*
+ * Validate that all compiler options of the given project match keys and values
+ * described in {@link JavaScriptCore#getDefaultOptions()} method.
+ *
+ * @param compilerOptions Map of options
+ * @return a status object with code IStatus.OK
if all
+ * compiler options are valid, otherwise a status object indicating what is wrong
+ * with the keys and their value.
+ */
+ /*
+ public static IStatus validateCompilerOptions(Map compilerOptions) {
+
+ // Get current options
+ String compliance = (String) compilerOptions.get(JavaScriptCore.COMPILER_COMPLIANCE);
+ String source = (String) compilerOptions.get(JavaScriptCore.COMPILER_SOURCE);
+ String target = (String) compilerOptions.get(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM);
+ if (compliance == null && source == null && target == null) {
+ return JavaModelStatus.VERIFIED_OK; // default is OK
+ }
+
+ // Initialize multi-status
+ List errors = new ArrayList();
+
+ // Set default for compliance if necessary (not set on project and not inherited...)
+ if (compliance == null) {
+ compliance = JavaScriptCore.getOption(JavaScriptCore.COMPILER_COMPLIANCE);
+ }
+
+ // Verify compliance level value and set source and target default if necessary
+ long complianceLevel = 0;
+ long sourceLevel = 0;
+ long targetLevel = 0;
+ if (JavaScriptCore.VERSION_1_3.equals(compliance)) {
+ complianceLevel = ClassFileConstants.JDK1_3;
+ if (source == null) {
+ source = JavaScriptCore.VERSION_1_3;
+ sourceLevel = ClassFileConstants.JDK1_3;
+ }
+ if (target == null) {
+ target = JavaScriptCore.VERSION_1_1;
+ targetLevel = ClassFileConstants.JDK1_1;
+ }
+ } else if (JavaScriptCore.VERSION_1_4.equals(compliance)) {
+ complianceLevel = ClassFileConstants.JDK1_4;
+ if (source == null) {
+ source = JavaScriptCore.VERSION_1_3;
+ sourceLevel = ClassFileConstants.JDK1_3;
+ }
+ if (target == null) {
+ target = JavaScriptCore.VERSION_1_2;
+ targetLevel = ClassFileConstants.JDK1_2;
+ }
+ } else if (JavaScriptCore.VERSION_1_5.equals(compliance)) {
+ complianceLevel = ClassFileConstants.JDK1_5;
+ if (source == null) {
+ source = JavaScriptCore.VERSION_1_5;
+ sourceLevel = ClassFileConstants.JDK1_5;
+ }
+ if (target == null) {
+ target = JavaScriptCore.VERSION_1_5;
+ targetLevel = ClassFileConstants.JDK1_5;
+ }
+ } else {
+ // compliance is not valid
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", compliance==null?"":compliance, JavaScriptCore.COMPILER_COMPLIANCE))); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // Verify source value and set default for target if necessary
+ if (JavaScriptCore.VERSION_1_4.equals(source)) {
+ sourceLevel = ClassFileConstants.JDK1_4;
+ if (target == null) {
+ target = JavaScriptCore.VERSION_1_4;
+ targetLevel = ClassFileConstants.JDK1_4;
+ }
+ } else if (JavaScriptCore.VERSION_1_5.equals(source)) {
+ sourceLevel = ClassFileConstants.JDK1_5;
+ if (target == null) {
+ target = JavaScriptCore.VERSION_1_5;
+ targetLevel = ClassFileConstants.JDK1_5;
+ }
+ } else if (JavaScriptCore.VERSION_1_3.equals(source)) {
+ sourceLevel = ClassFileConstants.JDK1_3;
+ } else {
+ // source is not valid
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", source==null?"":source, JavaScriptCore.COMPILER_SOURCE))); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // Verify target value
+ if (targetLevel == 0) {
+ targetLevel = CompilerOptions.versionToJdkLevel(target);
+ if (targetLevel == 0) {
+ // target is not valid
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", target==null?"":target, JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM))); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ // Check and set compliance/source/target compatibilities (only if they have valid values)
+ if (complianceLevel != 0 && sourceLevel != 0 && targetLevel != 0) {
+ // target must be 1.5 if source is 1.5
+ if (sourceLevel >= ClassFileConstants.JDK1_5 && targetLevel < ClassFileConstants.JDK1_5) {
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleTargetForSource", target, JavaScriptCore.VERSION_1_5))); //$NON-NLS-1$
+ }
+ else
+ // target must be 1.4 if source is 1.4
+ if (sourceLevel >= ClassFileConstants.JDK1_4 && targetLevel < ClassFileConstants.JDK1_4) {
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleTargetForSource", target, JavaScriptCore.VERSION_1_4))); //$NON-NLS-1$
+ }
+ // target cannot be greater than compliance level
+ if (complianceLevel < targetLevel){
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForTarget", compliance, JavaScriptCore.VERSION_1_4))); //$NON-NLS-1$
+ }
+ // compliance must be 1.5 if source is 1.5
+ if (source.equals(JavaScriptCore.VERSION_1_5) && complianceLevel < ClassFileConstants.JDK1_5) {
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForSource", compliance, JavaScriptCore.VERSION_1_5))); //$NON-NLS-1$
+ } else
+ // compliance must be 1.4 if source is 1.4
+ if (source.equals(JavaScriptCore.VERSION_1_4) && complianceLevel < ClassFileConstants.JDK1_4) {
+ errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForSource", compliance, JavaScriptCore.VERSION_1_4))); //$NON-NLS-1$
+ }
+ }
+
+ // Return status
+ int size = errors.size();
+ switch (size) {
+ case 0:
+ return JavaModelStatus.VERIFIED_OK;
+ case 1:
+ return (IStatus) errors.get(0);
+ default:
+ IJavaScriptModelStatus[] allStatus = new IJavaScriptModelStatus[size];
+ errors.toArray(allStatus);
+ return JavaModelStatus.newMultiStatus(allStatus);
+ }
+ }
+ */
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JavaScriptCore.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JavaScriptCore.java
new file mode 100644
index 0000000..bd7147c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JavaScriptCore.java
@@ -0,0 +1,4115 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE
+ * COMPILER_PB_STATIC_ACCESS_RECEIVER
+ * COMPILER_TASK_TAGS
+ * CORE_CIRCULAR_CLASSPATH
+ * CORE_INCOMPLETE_CLASSPATH
+ * IBM Corporation - added run(IWorkspaceRunnable, IProgressMonitor)
+ * IBM Corporation - added exclusion patterns to source includepath entries
+ * IBM Corporation - added specific output location to source includepath entries
+ * IBM Corporation - added the following constants:
+ * CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER
+ * CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER
+ * CLEAN
+ * IBM Corporation - added getJsGlobalScopeContainerInitializer(String)
+ * IBM Corporation - added the following constants:
+ * CODEASSIST_ARGUMENT_PREFIXES
+ * CODEASSIST_ARGUMENT_SUFFIXES
+ * CODEASSIST_FIELD_PREFIXES
+ * CODEASSIST_FIELD_SUFFIXES
+ * CODEASSIST_LOCAL_PREFIXES
+ * CODEASSIST_LOCAL_SUFFIXES
+ * CODEASSIST_STATIC_FIELD_PREFIXES
+ * CODEASSIST_STATIC_FIELD_SUFFIXES
+ * COMPILER_PB_CHAR_ARRAY_IN_STRING_CONCATENATION
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_LOCAL_VARIABLE_HIDING
+ * COMPILER_PB_SPECIAL_PARAMETER_HIDING_FIELD
+ * COMPILER_PB_FIELD_HIDING
+ * COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT
+ * CORE_INCOMPATIBLE_JDK_LEVEL
+ * VERSION_1_5
+ * COMPILER_PB_EMPTY_STATEMENT
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_INDIRECT_STATIC_ACCESS
+ * COMPILER_PB_BOOLEAN_METHOD_THROWING_EXCEPTION
+ * COMPILER_PB_UNNECESSARY_CAST
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_INVALID_JAVADOC
+ * COMPILER_PB_INVALID_JAVADOC_TAGS
+ * COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY
+ * COMPILER_PB_MISSING_JAVADOC_TAGS
+ * COMPILER_PB_MISSING_JAVADOC_TAGS_VISIBILITY
+ * COMPILER_PB_MISSING_JAVADOC_TAGS_OVERRIDING
+ * COMPILER_PB_MISSING_JAVADOC_COMMENTS
+ * COMPILER_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY
+ * COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING
+ * COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD
+ * COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING
+ * IBM Corporation - added the following constants:
+ * TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_FALLTHROUGH_CASE
+ * COMPILER_PB_PARAMETER_ASSIGNMENT
+ * COMPILER_PB_NULL_REFERENCE
+ * IBM Corporation - added the following constants:
+ * CODEASSIST_DEPRECATION_CHECK
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
+import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope;
+import org.eclipse.wst.jsdt.core.search.SearchEngine;
+import org.eclipse.wst.jsdt.core.search.SearchPattern;
+import org.eclipse.wst.jsdt.core.search.TypeNameRequestor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.wst.jsdt.internal.core.BatchOperation;
+import org.eclipse.wst.jsdt.internal.core.ClasspathAccessRule;
+import org.eclipse.wst.jsdt.internal.core.ClasspathAttribute;
+import org.eclipse.wst.jsdt.internal.core.ClasspathEntry;
+import org.eclipse.wst.jsdt.internal.core.CreateTypeHierarchyOperation;
+import org.eclipse.wst.jsdt.internal.core.DefaultWorkingCopyOwner;
+import org.eclipse.wst.jsdt.internal.core.JavaModel;
+import org.eclipse.wst.jsdt.internal.core.JavaModelManager;
+import org.eclipse.wst.jsdt.internal.core.JavaProject;
+import org.eclipse.wst.jsdt.internal.core.Region;
+import org.eclipse.wst.jsdt.internal.core.SetContainerOperation;
+import org.eclipse.wst.jsdt.internal.core.SetVariablesOperation;
+import org.eclipse.wst.jsdt.internal.core.UserLibraryManager;
+import org.eclipse.wst.jsdt.internal.core.builder.JavaBuilder;
+import org.eclipse.wst.jsdt.internal.core.builder.State;
+import org.eclipse.wst.jsdt.internal.core.util.MementoTokenizer;
+import org.eclipse.wst.jsdt.internal.core.util.Messages;
+import org.eclipse.wst.jsdt.internal.core.util.Util;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The plug-in runtime class for the JavaScript model plug-in containing the core
+ * (UI-free) support for JavaScript projects.
+ *
+ * Like all plug-in runtime classes (subclasses of Plugin
), this
+ * class is automatically instantiated by the platform when the plug-in gets
+ * activated. Clients must not attempt to instantiate plug-in runtime classes
+ * directly.
+ *
+ * The single instance of this class can be accessed from any plug-in declaring
+ * the JavaScript model plug-in as a prerequisite via
+ * JavaScriptCore.getJavaCore()
. The JavaScript model plug-in will be activated
+ * automatically if not already active.
+ *
"org.eclipse.wst.jsdt.core"
).
+ */
+ public static final String PLUGIN_ID = "org.eclipse.wst.jsdt.core" ; //$NON-NLS-1$
+
+ /**
+ * The identifier for the JavaScript validator
+ * (value "org.eclipse.wst.jsdt.core.javascriptValidator"
).
+ */
+ public static final String BUILDER_ID = PLUGIN_ID + ".javascriptValidator" ; //$NON-NLS-1$
+
+ /**
+ * The identifier for the JavaScript model
+ * (value "org.eclipse.wst.jsdt.core.jsmodel"
).
+ */
+ public static final String MODEL_ID = PLUGIN_ID + ".jsmodel" ; //$NON-NLS-1$
+
+ /**
+ * The identifier for the JavaScript nature
+ * (value "org.eclipse.wst.jsdt.core.jsnature"
).
+ * The presence of this nature on a project indicates that it is
+ * JavaScript-capable.
+ *
+ * @see org.eclipse.core.resources.IProject#hasNature(java.lang.String)
+ */
+ public static final String NATURE_ID = PLUGIN_ID + ".jsNature" ; //$NON-NLS-1$
+
+ /**
+ * Name of the handle id attribute in a JavaScript marker.
+ */
+ protected static final String ATT_HANDLE_ID =
+ "org.eclipse.wst.jsdt.internal.core.JavaModelManager.handleId" ; //$NON-NLS-1$
+
+ /**
+ * Name of the User Library Container id.
+ */
+ public static final String USER_LIBRARY_CONTAINER_ID= "org.eclipse.wst.jsdt.USER_LIBRARY"; //$NON-NLS-1$
+
+ // *************** Possible IDs for configurable options. ********************
+
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_LOCAL_VARIABLE_ATTR = PLUGIN_ID + ".compiler.debug.localVariable"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_LINE_NUMBER_ATTR = PLUGIN_ID + ".compiler.debug.lineNumber"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_SOURCE_FILE_ATTR = PLUGIN_ID + ".compiler.debug.sourceFile"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_CODEGEN_UNUSED_LOCAL = PLUGIN_ID + ".compiler.codegen.unusedLocal"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_CODEGEN_TARGET_PLATFORM = PLUGIN_ID + ".compiler.codegen.targetPlatform"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_CODEGEN_INLINE_JSR_BYTECODE = PLUGIN_ID + ".compiler.codegen.inlineJsrBytecode"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_DOC_COMMENT_SUPPORT = PLUGIN_ID + ".compiler.doc.comment.support"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @deprecated - discontinued since turning off would violate language specs
+ */
+ public static final String COMPILER_PB_UNREACHABLE_CODE = PLUGIN_ID + ".compiler.problem.unreachableCode"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @deprecated - discontinued since turning off would violate language specs
+ */
+ public static final String COMPILER_PB_INVALID_IMPORT = PLUGIN_ID + ".compiler.problem.invalidImport"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNDEFINED_FIELD = PLUGIN_ID + ".compiler.problem.undefinedField"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME = PLUGIN_ID + ".compiler.problem.methodWithConstructorName"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_DEPRECATION = PLUGIN_ID + ".compiler.problem.deprecation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE = PLUGIN_ID + ".compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD = "org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_HIDDEN_CATCH_BLOCK = PLUGIN_ID + ".compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_LOCAL = PLUGIN_ID + ".compiler.problem.unusedLocal"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_PARAMETER = PLUGIN_ID + ".compiler.problem.unusedParameter"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_PARAMETER_WHEN_IMPLEMENTING_ABSTRACT = PLUGIN_ID + ".compiler.problem.unusedParameterWhenImplementingAbstract"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_PARAMETER_WHEN_OVERRIDING_CONCRETE = PLUGIN_ID + ".compiler.problem.unusedParameterWhenOverridingConcrete"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_PARAMETER_INCLUDE_DOC_COMMENT_REFERENCE = PLUGIN_ID + ".compiler.problem.unusedParameterIncludeDocCommentReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_IMPORT = PLUGIN_ID + ".compiler.problem.unusedImport"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_NON_NLS_STRING_LITERAL = PLUGIN_ID + ".compiler.problem.nonExternalizedStringLiteral"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_ASSERT_IDENTIFIER = PLUGIN_ID + ".compiler.problem.assertIdentifier"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_STATIC_ACCESS_RECEIVER = PLUGIN_ID + ".compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_INDIRECT_STATIC_ACCESS = PLUGIN_ID + ".compiler.problem.indirectStaticAccess"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_NO_EFFECT_ASSIGNMENT = PLUGIN_ID + ".compiler.problem.noEffectAssignment"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_PRIVATE_MEMBER = PLUGIN_ID + ".compiler.problem.unusedPrivateMember"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_LOCAL_VARIABLE_HIDING = PLUGIN_ID + ".compiler.problem.localVariableHiding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_SPECIAL_PARAMETER_HIDING_FIELD = PLUGIN_ID + ".compiler.problem.specialParameterHidingField"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_FIELD_HIDING = PLUGIN_ID + ".compiler.problem.fieldHiding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_TYPE_PARAMETER_HIDING = PLUGIN_ID + ".compiler.problem.typeParameterHiding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT = PLUGIN_ID + ".compiler.problem.possibleAccidentalBooleanAssignment"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_FALLTHROUGH_CASE = PLUGIN_ID + ".compiler.problem.fallthroughCase"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_EMPTY_STATEMENT = PLUGIN_ID + ".compiler.problem.emptyStatement"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_BOOLEAN_METHOD_THROWING_EXCEPTION = PLUGIN_ID + ".compiler.problem.booleanMethodThrowingException"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNNECESSARY_TYPE_CHECK = PLUGIN_ID + ".compiler.problem.unnecessaryTypeCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNNECESSARY_ELSE = PLUGIN_ID + ".compiler.problem.unnecessaryElse"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNDOCUMENTED_EMPTY_BLOCK = PLUGIN_ID + ".compiler.problem.undocumentedEmptyBlock"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_FINALLY_BLOCK_NOT_COMPLETING = PLUGIN_ID + ".compiler.problem.finallyBlockNotCompletingNormally"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION = PLUGIN_ID + ".compiler.problem.unusedDeclaredThrownException"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING = PLUGIN_ID + ".compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNQUALIFIED_FIELD_ACCESS = PLUGIN_ID + ".compiler.problem.unqualifiedFieldAccess"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @deprecated - got renamed into {@link #COMPILER_PB_UNCHECKED_TYPE_OPERATION}
+ */
+ public static final String COMPILER_PB_UNSAFE_TYPE_OPERATION = PLUGIN_ID + ".compiler.problem.uncheckedTypeOperation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNCHECKED_TYPE_OPERATION = PLUGIN_ID + ".compiler.problem.uncheckedTypeOperation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_RAW_TYPE_REFERENCE = PLUGIN_ID + ".compiler.problem.rawTypeReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_FINAL_PARAMETER_BOUND = PLUGIN_ID + ".compiler.problem.finalParameterBound"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST = PLUGIN_ID + ".compiler.problem.varargsArgumentNeedCast"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_OVERRIDE_ANNOTATION = PLUGIN_ID + ".compiler.problem.missingOverrideAnnotation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_DEPRECATED_ANNOTATION = PLUGIN_ID + ".compiler.problem.missingDeprecatedAnnotation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNUSED_LABEL = PLUGIN_ID + ".compiler.problem.unusedLabel"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_INVALID_JAVADOC = PLUGIN_ID + ".compiler.problem.invalidJavadoc"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_INVALID_JAVADOC_TAGS = PLUGIN_ID + ".compiler.problem.invalidJavadocTags"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_INVALID_JAVADOC_TAGS__DEPRECATED_REF = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsDeprecatedRef"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_INVALID_JAVADOC_TAGS__NOT_VISIBLE_REF = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsNotVisibleRef"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_JAVADOC_TAGS = PLUGIN_ID + ".compiler.problem.missingJavadocTags"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_JAVADOC_TAGS_VISIBILITY = PLUGIN_ID + ".compiler.problem.missingJavadocTagsVisibility"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_JAVADOC_TAGS_OVERRIDING = PLUGIN_ID + ".compiler.problem.missingJavadocTagsOverriding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_JAVADOC_COMMENTS = PLUGIN_ID + ".compiler.problem.missingJavadocComments"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY = PLUGIN_ID + ".compiler.problem.missingJavadocCommentsVisibility"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING = PLUGIN_ID + ".compiler.problem.missingJavadocCommentsOverriding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_MAX_PER_UNIT = PLUGIN_ID + ".compiler.maxProblemPerUnit"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_FATAL_OPTIONAL_ERROR = PLUGIN_ID + ".compiler.problem.fatalOptionalError"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_PARAMETER_ASSIGNMENT = PLUGIN_ID + ".compiler.problem.parameterAssignment"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_SEMANTIC_VALIDATION = "semanticValidation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_SOURCE = PLUGIN_ID + ".compiler.source"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_COMPLIANCE = PLUGIN_ID + ".compiler.compliance"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_TASK_PRIORITIES = PLUGIN_ID + ".compiler.taskPriorities"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value for COMPILER_TASK_PRIORITIES.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_TASK_PRIORITY_HIGH = "HIGH"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value for COMPILER_TASK_PRIORITIES.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_TASK_PRIORITY_LOW = "LOW"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value for COMPILER_TASK_PRIORITIES.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_TASK_PRIORITY_NORMAL = "NORMAL"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_TASK_TAGS = PLUGIN_ID + ".compiler.taskTags"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_TASK_CASE_SENSITIVE = PLUGIN_ID + ".compiler.taskCaseSensitive"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_FORBIDDEN_REFERENCE = PLUGIN_ID + ".compiler.problem.forbiddenReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_DISCOURAGED_REFERENCE = PLUGIN_ID + ".compiler.problem.discouragedReference"; //$NON-NLS-1$
+
+ /* START -------------------------------- Bug 203292 Type/Method/Filed resolution error configuration --------------------- */
+ public static final String UNRESOLVED_TYPE_REFERENCE = PLUGIN_ID + ".compiler.problem.unresolvedTypeReference"; //$NON-NLS-1$
+ public static final String UNRESOLVED_FIELD_REFERENCE = PLUGIN_ID + ".compiler.problem.unresolvedFieldReference"; //$NON-NLS-1$
+ public static final String UNRESOLVED_METHOD_REFERENCE = PLUGIN_ID + ".compiler.problem.unresolvedMethodReference"; //$NON-NLS-1$
+ /* END -------------------------------- Bug 203292 Type/Method/Filed resolution error configuration --------------------- */
+
+ /* START -------------------------------- Bug 197884 Loosly defined var (for statement) and optional semi-colon --------------------- */
+ public static final String LOOSE_VAR_DECL = PLUGIN_ID + ".compiler.problem.looseVarDecleration"; //$NON-NLS-1$
+ public static final String OPTIONAL_SEMICOLON = PLUGIN_ID + ".compiler.problem.optionalSemicolon"; //$NON-NLS-1$
+ /* END -------------------------------- Bug 197884 Loosly defined var (for statement) and optional semi-colon --------------------- */
+
+
+ /**
+
+ *
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_SUPPRESS_WARNINGS = PLUGIN_ID + ".compiler.problem.suppressWarnings"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNHANDLED_WARNING_TOKEN = PLUGIN_ID + ".compiler.problem.unhandledWarningToken"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_NULL_REFERENCE = PLUGIN_ID + ".compiler.problem.nullReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_POTENTIAL_NULL_REFERENCE = PLUGIN_ID + ".compiler.problem.potentialNullReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_DUPLICATE_LOCAL_VARIABLES = PLUGIN_ID + ".compiler.problem.duplicateLocalVariables"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_REDUNDANT_NULL_CHECK = PLUGIN_ID + ".compiler.problem.redundantNullCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNINITIALIZED_LOCAL_VARIABLE = PLUGIN_ID + ".compiler.problem.uninitializedLocalVariable"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_UNINITIALIZED_GLOBAL_VARIABLE = PLUGIN_ID + ".compiler.problem.uninitializedGlobalVariable"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPILER_PB_OVERRIDING_METHOD_WITHOUT_SUPER_INVOCATION = PLUGIN_ID + ".compiler.problem.overridingMethodWithoutSuperInvocation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_JAVA_BUILD_ORDER = PLUGIN_ID + ".computeJavaBuildOrder"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_JAVA_BUILD_RESOURCE_COPY_FILTER = PLUGIN_ID + ".builder.resourceCopyExclusionFilter"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_JAVA_BUILD_DUPLICATE_RESOURCE = PLUGIN_ID + ".builder.duplicateResourceTask"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER = PLUGIN_ID + ".builder.cleanOutputFolder"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER = PLUGIN_ID + ".builder.recreateModifiedClassFileInOutputFolder"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_INCOMPLETE_CLASSPATH = PLUGIN_ID + ".incompleteClasspath"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_CIRCULAR_CLASSPATH = PLUGIN_ID + ".circularClasspath"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_INCOMPATIBLE_JDK_LEVEL = PLUGIN_ID + ".incompatibleJDKLevel"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_JAVA_BUILD_INVALID_CLASSPATH = PLUGIN_ID + ".builder.invalidClasspath"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS = PLUGIN_ID + ".classpath.exclusionPatterns"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS = PLUGIN_ID + ".classpath.multipleOutputLocations"; //$NON-NLS-1$
+ /**
+ * Default task tag
+ * @deprecated Use {@link #DEFAULT_TASK_TAGS} instead
+ */
+ public static final String DEFAULT_TASK_TAG = "TODO"; //$NON-NLS-1$
+ /**
+ * Default task priority
+ * @deprecated Use {@link #DEFAULT_TASK_PRIORITIES} instead
+ */
+ public static final String DEFAULT_TASK_PRIORITY = "NORMAL"; //$NON-NLS-1$
+ /**
+ * Default task tag
+ */
+ public static final String DEFAULT_TASK_TAGS = "TODO,FIXME,XXX"; //$NON-NLS-1$
+ /**
+ * Default task priority
+ */
+ public static final String DEFAULT_TASK_PRIORITIES = "NORMAL,HIGH,NORMAL"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_VISIBILITY_CHECK = PLUGIN_ID + ".codeComplete.visibilityCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_DEPRECATION_CHECK = PLUGIN_ID + ".codeComplete.deprecationCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_CAMEL_CASE_MATCH = PLUGIN_ID + ".codeComplete.camelCaseMatch"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_IMPLICIT_QUALIFICATION = PLUGIN_ID + ".codeComplete.forceImplicitQualification"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_FIELD_PREFIXES = PLUGIN_ID + ".codeComplete.fieldPrefixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_STATIC_FIELD_PREFIXES = PLUGIN_ID + ".codeComplete.staticFieldPrefixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_LOCAL_PREFIXES = PLUGIN_ID + ".codeComplete.localPrefixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_ARGUMENT_PREFIXES = PLUGIN_ID + ".codeComplete.argumentPrefixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_FIELD_SUFFIXES = PLUGIN_ID + ".codeComplete.fieldSuffixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_STATIC_FIELD_SUFFIXES = PLUGIN_ID + ".codeComplete.staticFieldSuffixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_LOCAL_SUFFIXES = PLUGIN_ID + ".codeComplete.localSuffixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_ARGUMENT_SUFFIXES = PLUGIN_ID + ".codeComplete.argumentSuffixes"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_FORBIDDEN_REFERENCE_CHECK= PLUGIN_ID + ".codeComplete.forbiddenReferenceCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_DISCOURAGED_REFERENCE_CHECK= PLUGIN_ID + ".codeComplete.discouragedReferenceCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String CODEASSIST_SUGGEST_STATIC_IMPORTS= PLUGIN_ID + ".codeComplete.suggestStaticImports"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ */
+ public static final String TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC = PLUGIN_ID + ".timeoutForParameterNameFromAttachedJavadoc"; //$NON-NLS-1$
+
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String GENERATE = "generate"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String DO_NOT_GENERATE = "do not generate"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String PRESERVE = "preserve"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String OPTIMIZE_OUT = "optimize out"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_1 = "1.1"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_2 = "1.2"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_3 = "1.3"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_4 = "1.4"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_5 = "1.5"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_6 = "1.6"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String VERSION_1_7 = "1.7"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String ABORT = "abort"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String ERROR = "error"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String WARNING = "warning"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String IGNORE = "ignore"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPUTE = "compute"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String INSERT = "insert"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String DO_NOT_INSERT = "do not insert"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String PRESERVE_ONE = "preserve one"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String CLEAR_ALL = "clear all"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String NORMAL = "normal"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String COMPACT = "compact"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String TAB = "tab"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String SPACE = "space"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String ENABLED = "enabled"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String DISABLED = "disabled"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String CLEAN = "clean"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String PUBLIC = "public"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String PROTECTED = "protected"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String DEFAULT = "default"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String PRIVATE = "private"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ */
+ public static final String NEVER = "never"; //$NON-NLS-1$
+
+ /**
+ * Value of the content-type for JavaScript source files. Use this value to retrieve the JavaScript content type
+ * from the content type manager, and to add new JavaScript-like extensions to this content type.
+ *
+ * @see org.eclipse.core.runtime.content.IContentTypeManager#getContentType(String)
+ * @see #getJavaScriptLikeExtensions()
+ */
+ public static final String JAVA_SOURCE_CONTENT_TYPE = JavaScriptCore.PLUGIN_ID+".jsSource" ; //$NON-NLS-1$
+
+
+ public static final String READ_ONLY_SOURCE_PROPERTY = "readOnlyResource" ; //$NON-NLS-1$
+
+ /**
+ * Creates the JavaScript core plug-in.
+ * + * The plug-in instance is created automatically by the + * Eclipse platform. Clients must not call. + *
+ * + */ + public JavaScriptCore() { + super(); + JAVA_CORE_PLUGIN = this; + } + + /** + * Adds the given listener for changes to JavaScript elements. + * Has no effect if an identical listener is already registered. + * + * This listener will only be notified during the POST_CHANGE resource change notification + * and any reconcile operation (POST_RECONCILE). + * For finer control of the notification, useaddElementChangedListener(IElementChangedListener,int)
,
+ * which allows to specify a different eventMask.
+ *
+ * @param listener the listener
+ * @see ElementChangedEvent
+ */
+ public static void addElementChangedListener(IElementChangedListener listener) {
+ addElementChangedListener(listener, ElementChangedEvent.POST_CHANGE | ElementChangedEvent.POST_RECONCILE);
+ }
+
+ /**
+ * Adds the given listener for changes to JavaScript elements.
+ * Has no effect if an identical listener is already registered.
+ * After completion of this method, the given listener will be registered for exactly
+ * the specified events. If they were previously registered for other events, they
+ * will be deregistered.
+ * + * Once registered, a listener starts receiving notification of changes to + * javaScript elements in the model. The listener continues to receive + * notifications until it is replaced or removed. + *
+ *
+ * Listeners can listen for several types of event as defined in ElementChangeEvent
.
+ * Clients are free to register for any number of event types however if they register
+ * for more than one, it is their responsibility to ensure they correctly handle the
+ * case where the same javaScript element change shows up in multiple notifications.
+ * Clients are guaranteed to receive only the events for which they are registered.
+ *
String
,
+ * value type: String
)
+ * @param element the JavaScript element for which the marker needs to be configured
+ */
+ public static void addJavaScriptElementMarkerAttributes(
+ Map attributes,
+ IJavaScriptElement element) {
+ if (element instanceof IMember)
+ element = ((IMember) element).getClassFile();
+ if (attributes != null && element != null)
+ attributes.put(ATT_HANDLE_ID, element.getHandleIdentifier());
+ }
+
+ /**
+ * Adds the given listener for resource change events of the given types to the JavaScript core.
+ * The listener is guaranteed to be notified of the resource change event before
+ * the JavaScript core starts processing the resource change event itself.
+ * + * If an identical listener is already registered, the given event types are added to the event types + * of interest to the listener. + *
+ *+ * Supported event types are: + *
IMarker.setAttribute
on the marker fails
+ */
+ public void configureJavaScriptElementMarker(IMarker marker, IJavaScriptElement element)
+ throws CoreException {
+ if (element instanceof IMember)
+ element = ((IMember) element).getClassFile();
+ if (marker != null && element != null)
+ marker.setAttribute(ATT_HANDLE_ID, element.getHandleIdentifier());
+ }
+
+ /**
+ * Returns the JavaScript model element corresponding to the given handle identifier
+ * generated by IJavaScriptElement.getHandleIdentifier()
, or
+ * null
if unable to create the associated element.
+ *
+ * @param handleIdentifier the given handle identifier
+ * @return the JavaScript element corresponding to the handle identifier
+ */
+ public static IJavaScriptElement create(String handleIdentifier) {
+ return create(handleIdentifier, DefaultWorkingCopyOwner.PRIMARY);
+ }
+
+ /**
+ * Returns the JavaScript model element corresponding to the given handle identifier
+ * generated by IJavaScriptElement.getHandleIdentifier()
, or
+ * null
if unable to create the associated element.
+ * If the returned JavaScript element is an IJavaScriptUnit
, its owner
+ * is the given owner if such a working copy exists, otherwise the javaScript unit
+ * is a primary javaScript unit.
+ *
+ * @param handleIdentifier the given handle identifier
+ * @param owner the owner of the returned javaScript unit, ignored if the returned
+ * element is not a javaScript unit
+ * @return the JavaScript element corresponding to the handle identifier
+ */
+ public static IJavaScriptElement create(String handleIdentifier, WorkingCopyOwner owner) {
+ if (handleIdentifier == null) {
+ return null;
+ }
+ MementoTokenizer memento = new MementoTokenizer(handleIdentifier);
+ JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
+ return model.getHandleFromMemento(memento, owner);
+ }
+
+ /**
+ * Returns the JavaScript element corresponding to the given file, or
+ * null
if unable to associate the given file
+ * with a JavaScript element.
+ *
+ * The file must be one of:
IJavaScriptUnit
.class
file - the element returned is the corresponding IClassFile
.jar
file - the element returned is the corresponding IPackageFragmentRoot
+ * Creating a JavaScript element has the side effect of creating and opening all of the
+ * element's parents if they are not yet open.
+ *
+ * @param file the given file
+ * @return the JavaScript element corresponding to the given file, or
+ * null
if unable to associate the given file
+ * with a JavaScript element
+ */
+ public static IJavaScriptElement create(IFile file) {
+ return JavaModelManager.create(file, null/*unknown javaScript project*/);
+ }
+ /**
+ * Returns the source folder (package fragment or package fragment root) corresponding to the given folder, or
+ * null
if unable to associate the given folder with a JavaScript element.
+ *
+ * Note that a package fragment root is returned rather than a default package. + *
+ * Creating a JavaScript element has the side effect of creating and opening all of the
+ * element's parents if they are not yet open.
+ *
+ * @param folder the given folder
+ * @return the package fragment or package fragment root corresponding to the given folder, or
+ * null
if unable to associate the given folder with a JavaScript element
+ */
+ public static IJavaScriptElement create(IFolder folder) {
+ return JavaModelManager.create(folder, null/*unknown javaScript project*/);
+ }
+ /**
+ * Returns the JavaScript project corresponding to the given project.
+ *
+ * Creating a JavaScript Project has the side effect of creating and opening all of the + * project's parents if they are not yet open. + *
+ * Note that no check is done at this time on the existence or the javaScript nature of this project.
+ *
+ * @param project the given project
+ * @return the JavaScript project corresponding to the given project, null if the given project is null
+ */
+ public static IJavaScriptProject create(IProject project) {
+ if (project == null) {
+ return null;
+ }
+ JavaModel javaModel = JavaModelManager.getJavaModelManager().getJavaModel();
+ return javaModel.getJavaProject(project);
+ }
+ /**
+ * Returns the JavaScript element corresponding to the given resource, or
+ * null
if unable to associate the given resource
+ * with a JavaScript element.
+ *
+ * The resource must be one of:
IJavaScriptProject
IJavaScriptUnit
IPackageFragmentRoot
+ * or IPackageFragment
IJavaScriptModel
+ * Creating a JavaScript element has the side effect of creating and opening all of the
+ * element's parents if they are not yet open.
+ *
+ * @param resource the given resource
+ * @return the JavaScript element corresponding to the given resource, or
+ * null
if unable to associate the given resource
+ * with a JavaScript element
+ */
+ public static IJavaScriptElement create(IResource resource) {
+ return JavaModelManager.create(resource, null/*unknown javaScript project*/);
+ }
+ /**
+ * Returns the JavaScript element corresponding to the given file, its project being the given
+ * project. Returns null
if unable to associate the given resource
+ * with a JavaScript element.
+ *
+ * The resource must be one of:
IJavaScriptProject
IJavaScriptUnit
IPackageFragmentRoot
+ * or IPackageFragment
IJavaScriptModel
+ * Creating a JavaScript element has the side effect of creating and opening all of the
+ * element's parents if they are not yet open.
+ *
+ * @param resource the given resource
+ * @return the JavaScript element corresponding to the given file, or
+ * null
if unable to associate the given file
+ * with a JavaScript element
+ */
+ public static IJavaScriptElement create(IResource resource, IJavaScriptProject project) {
+ return JavaModelManager.create(resource, project);
+ }
+ /**
+ * Returns the JavaScript model.
+ *
+ * @param root the given root
+ * @return the JavaScript model, or null
if the root is null
+ */
+ public static IJavaScriptModel create(IWorkspaceRoot root) {
+ if (root == null) {
+ return null;
+ }
+ return JavaModelManager.getJavaModelManager().getJavaModel();
+ }
+ /*
+ * Creates and returns a class file element for
+ * the given .class
file. Returns null
if unable
+ * to recognize the class file.
+ *
+ * @param file the given .class
file
+ * @return a class file element for the given .class
file, or null
if unable
+ * to recognize the class file
+ */
+ public static IClassFile createClassFileFrom(IFile file) {
+ return JavaModelManager.createClassFileFrom(file, null);
+ }
+ /**
+ * Creates and returns a javaScript unit element for
+ * the given source file (i.e. a file with one of the {@link JavaScriptCore#getJavaScriptLikeExtensions()
+ * JavaScript-like extensions}). Returns null
if unable
+ * to recognize the javaScript unit.
+ *
+ * @param file the given source file
+ * @return a javaScript unit element for the given source file, or null
if unable
+ * to recognize the javaScript unit
+ */
+ public static IJavaScriptUnit createCompilationUnitFrom(IFile file) {
+ return JavaModelManager.createCompilationUnitFrom(file, null/*unknown javaScript project*/);
+ }
+ /*
+ * Creates and returns a handle for the given JAR file.
+ * The JavaScript model associated with the JAR's project may be
+ * created as a side effect.
+ *
+ * @param file the given JAR file
+ * @return a handle for the given JAR file, or null
if unable to create a JAR package fragment root.
+ * (for example, if the JAR file represents a non-JavaScript resource)
+ */
+ public static IPackageFragmentRoot createJarPackageFragmentRootFrom(IFile file) {
+ return JavaModelManager.createJarPackageFragmentRootFrom(file, null/*unknown javaScript project*/);
+ }
+
+ /**
+ * Answers the project specific value for a given includepath container.
+ * In case this container path could not be resolved, then will answer null
.
+ * Both the container path and the project context are supposed to be non-null.
+ *
+ * The containerPath is a formed by a first ID segment followed with extra segments, which can be
+ * used as additional hints for resolution. If no container was ever recorded for this container path
+ * onto this project (using setJsGlobalScopeContainer
, then a
+ * JsGlobalScopeContainerInitializer
will be activated if any was registered for this container
+ * ID onto the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer".
+ *
+ * There is no assumption that the returned container must answer the exact same containerPath
+ * when requested IJsGlobalScopeContainer#getPath
.
+ * Indeed, the containerPath is just an indication for resolving it to an actual container object.
+ *
+ * Includepath container values are persisted locally to the workspace, but
+ * are not preserved from a session to another. It is thus highly recommended to register a
+ * JsGlobalScopeContainerInitializer
for each referenced container
+ * (through the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer").
+ *
+ * @param containerPath the name of the container, which needs to be resolved
+ * @param project a specific project in which the container is being resolved
+ * @return the corresponding includepath container or null
if unable to find one.
+ *
+ * @exception JavaScriptModelException if an exception occurred while resolving the container, or if the resolved container
+ * contains illegal entries (contains CPE_CONTAINER entries or null entries).
+ *
+ * @see JsGlobalScopeContainerInitializer
+ * @see IJsGlobalScopeContainer
+ * @see #setJsGlobalScopeContainer(IPath, IJavaScriptProject[], IJsGlobalScopeContainer[], IProgressMonitor)
+ */
+ public static IJsGlobalScopeContainer getJsGlobalScopeContainer(IPath containerPath, IJavaScriptProject project) throws JavaScriptModelException {
+
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ IJsGlobalScopeContainer container = manager.getJsGlobalScopeContainer(containerPath, project);
+ if (container == JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
+ return manager.getPreviousSessionContainer(containerPath, project);
+ }
+ return container;
+ }
+
+ /**
+ * Helper method finding the includepath container initializer registered for a given includepath container ID
+ * or null
if none was found while iterating over the contributions to extension point to
+ * the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer".
+ *
+ * A containerID is the first segment of any container path, used to identify the registered container initializer. + *
+ * @param containerID - a containerID identifying a registered initializer
+ * @return JsGlobalScopeContainerInitializer - the registered includepath container initializer or null
if
+ * none was found.
+ */
+ public static JsGlobalScopeContainerInitializer getJsGlobalScopeContainerInitializer(String containerID) {
+ HashMap containerInitializersCache = JavaModelManager.getJavaModelManager().containerInitializersCache;
+ JsGlobalScopeContainerInitializer initializer = (JsGlobalScopeContainerInitializer) containerInitializersCache.get(containerID);
+ if (initializer == null) {
+ initializer = computeJsGlobalScopeContainerInitializer(containerID);
+ if (initializer == null)
+ return null;
+ containerInitializersCache.put(containerID, initializer);
+ }
+ return initializer;
+ }
+
+ private static JsGlobalScopeContainerInitializer computeJsGlobalScopeContainerInitializer(String containerID) {
+ Plugin jdtCorePlugin = JavaScriptCore.getPlugin();
+ if (jdtCorePlugin == null) return null;
+
+ IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaScriptCore.PLUGIN_ID, JavaModelManager.CPCONTAINER_INITIALIZER_EXTPOINT_ID);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for(int i = 0; i < extensions.length; i++){
+ IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
+ for(int j = 0; j < configElements.length; j++){
+ IConfigurationElement configurationElement = configElements[j];
+ String initializerID = configurationElement.getAttribute("id"); //$NON-NLS-1$
+ if (initializerID != null && initializerID.equals(containerID)){
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_found_container_initializer(containerID, configurationElement);
+ try {
+ Object execExt = configurationElement.createExecutableExtension("class"); //$NON-NLS-1$
+ if (execExt instanceof JsGlobalScopeContainerInitializer){
+ return (JsGlobalScopeContainerInitializer)execExt;
+ }
+ } catch(CoreException e) {
+ // executable extension could not be created: ignore this initializer
+ if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ verbose_failed_to_instanciate_container_initializer(containerID, configurationElement);
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static void verbose_failed_to_instanciate_container_initializer(String containerID, IConfigurationElement configurationElement) {
+ Util.verbose(
+ "CPContainer INIT - failed to instanciate initializer\n" + //$NON-NLS-1$
+ " container ID: " + containerID + '\n' + //$NON-NLS-1$
+ " class: " + configurationElement.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$
+ System.err);
+ }
+
+ private static void verbose_found_container_initializer(String containerID, IConfigurationElement configurationElement) {
+ Util.verbose(
+ "CPContainer INIT - found initializer\n" + //$NON-NLS-1$
+ " container ID: " + containerID + '\n' + //$NON-NLS-1$
+ " class: " + configurationElement.getAttribute("class")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+
+ /**
+ * Returns the path held in the given includepath variable.
+ * Returns null
if unable to bind.
+ *
+ * Includepath variable values are persisted locally to the workspace, and + * are preserved from session to session. + *
+ * Note that includepath variables can be contributed registered initializers for,
+ * using the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeVariableInitializer".
+ * If an initializer is registered for a variable, its persisted value will be ignored:
+ * its initializer will thus get the opportunity to rebind the variable differently on
+ * each session.
+ *
+ * @param variableName the name of the includepath variable
+ * @return the path, or null
if none
+ * @see #setClasspathVariable(String, IPath)
+ */
+ /**
+ * Returns the path held in the given includepath variable.
+ * Returns null
if unable to bind.
+ *
+ * Includepath variable values are persisted locally to the workspace, and + * are preserved from session to session. + *
+ * Note that includepath variables can be contributed registered initializers for,
+ * using the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeVariableInitializer".
+ * If an initializer is registered for a variable, its persisted value will be ignored:
+ * its initializer will thus get the opportunity to rebind the variable differently on
+ * each session.
+ *
+ * @param variableName the name of the includepath variable
+ * @return the path, or
+ * @param variable the given variable
+ * @return JsGlobalScopeVariableInitializer - the registered includepath variable initializer or
+ * Includepath variable values are persisted locally to the workspace, and
+ * are preserved from session to session.
+ *
+ *
+ * @return the list of includepath variable names
+ * @see #setIncludepathVariable(String, IPath)
+ */
+ public static String[] getIncludepathVariableNames() {
+ return JavaModelManager.getJavaModelManager().variableNames();
+ }
+
+ /**
+ * Returns a table of all known configurable options with their default values.
+ * These options allow to configure the behaviour of the underlying components.
+ * The client may safely use the result as a template that they can modify and
+ * then pass to The contents of the array is accurate only if the elements of the given region have been built. The given region can contain instances of: All other types of
+ * For a complete description of the configurable options, see For a complete description of the configurable options, see Returns a default set of options even if the platform is not running.
+ * Variable source attachment path and root path are also resolved and recorded in the resulting includepath entry.
+ *
+ * NOTE: This helper method does not handle includepath containers, for which should rather be used
+ *
+ *
+ * @param entry the given variable entry
+ * @return the resolved library or project includepath entry, or
+ * However calling this method is optional. Services will lazily perform
+ * initialization when invoked. This is only a way to reduce initialization
+ * overhead on user actions, if it can be performed before at some
+ * appropriate moment.
+ *
+ * This initialization runs accross all JavaScript projects in the workspace. Thus the
+ * workspace root scheduling rule is used during this operation.
+ *
+ * This method may return before the initialization is complete. The
+ * initialization will then continue in a background thread.
+ *
+ * This method can be called concurrently.
+ *
+ * The rule kind is one of {@link IAccessRule#K_ACCESSIBLE}, {@link IAccessRule#K_DISCOURAGED},
+ * or {@link IAccessRule#K_NON_ACCESSIBLE}, optionally combined with {@link IAccessRule#IGNORE_IF_BETTER},
+ * e..g.
+ * @param containerPath the path identifying the container
+ * @return a new container includepath entry
+ *
+ * @see JavaScriptCore#getJsGlobalScopeContainer(IPath, IJavaScriptProject)
+ */
+ public static IIncludePathEntry newContainerEntry(IPath containerPath) {
+ return newContainerEntry(
+ containerPath,
+ ClasspathEntry.NO_ACCESS_RULES,
+ ClasspathEntry.NO_EXTRA_ATTRIBUTES,
+ false/*not exported*/);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind
+ * A container entry allows to express indirect references to a set of libraries, projects and variable entries,
+ * which can be interpreted differently for each JavaScript project where it is used.
+ * A includepath container entry can be resolved using
+ * A container is exclusively resolved by a
+ * A container path must be formed of at least one segment, where:
+ * Example of an JsGlobalScopeContainerInitializer for a includepath container denoting a default JDK container:
+ *
+ * The access rules determine the set of accessible source and class files
+ * in the container. If the list of access rules is empty, then all files
+ * in this container are accessible.
+ * See {@link IAccessRule} for a detailed description of access
+ * rules. Note that if an entry defined by the container defines access rules,
+ * then these access rules are combined with the given access rules.
+ * The given access rules are considered first, then the entry's access rules are
+ * considered.
+ *
+ * The
+ * The
+ * Note that this operation does not attempt to validate includepath containers
+ * or access the resources at the given paths.
+ *
+ * Note that if a working copy is empty, it will be as if the original compilation
+ * unit had been deleted.
+ *
+ *
+ * @param monitor the given progress monitor
+ * @param region the given region
+ * @param owner the owner of working copies that take precedence over their original javaScript units,
+ * or
+ * A library entry is used to denote a prerequisite JAR or root folder containing binaries.
+ * The target JAR can either be defined internally to the workspace (absolute path relative
+ * to the workspace root) or externally to the workspace (absolute path in the file system).
+ * The target root folder can only be defined internally to the workspace (absolute path relative
+ * to the workspace root). To use a binary folder external to the workspace, it must first be
+ * linked (see IFolder#createLink(...)).
+ *
+ *
+ * The
+ * The
+ * A library entry is used to denote a prerequisite JAR or root folder containing binaries.
+ * The target JAR can either be defined internally to the workspace (absolute path relative
+ * to the workspace root) or externally to the workspace (absolute path in the file system).
+ * The target root folder can only be defined internally to the workspace (absolute path relative
+ * to the workspace root). To use a binary folder external to the workspace, it must first be
+ * linked (see IFolder#createLink(...)).
+ *
+ *
+ * The
+ * The
+ * A project entry is used to denote a prerequisite project on a includepath.
+ * The referenced project will be contributed as a whole, either as sources (in the JavaScript Model, it
+ * contributes all its package fragment roots) or as binaries (when building, it contributes its
+ * whole output location).
+ *
+ * A project reference allows to indirect through another project, independently from its internal layout.
+ *
+ * The prerequisite project is referred to using an absolute path relative to the workspace root.
+ *
+ * The access rules determine the set of accessible class files
+ * in the project. If the list of access rules is empty then all files
+ * in this project are accessible.
+ * See {@link IAccessRule} for a detailed description of access rules.
+ *
+ * The
+ * The
+ * The
+ * The convenience method is fully equivalent to:
+ * null
if none
+ * @see #setIncludepathVariable(String, IPath)
+ */
+ public static IPath getIncludepathVariable(final String variableName) {
+
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ IPath variablePath = manager.variableGet(variableName);
+ if (variablePath == JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS){
+ return manager.getPreviousSessionVariable(variableName);
+ }
+
+ if (variablePath != null) {
+ if (variablePath == JavaModelManager.CP_ENTRY_IGNORE_PATH)
+ return null;
+ return variablePath;
+ }
+
+ // even if persisted value exists, initializer is given priority, only if no initializer is found the persisted value is reused
+ final JsGlobalScopeVariableInitializer initializer = JavaScriptCore.getJsGlobalScopeVariableInitializer(variableName);
+ if (initializer != null){
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ verbose_triggering_variable_initialization(variableName, initializer);
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_triggering_variable_initialization_invocation_trace();
+ manager.variablePut(variableName, JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS); // avoid initialization cycles
+ boolean ok = false;
+ try {
+ // let OperationCanceledException go through
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59363)
+ initializer.initialize(variableName);
+
+ variablePath = manager.variableGet(variableName); // initializer should have performed side-effect
+ if (variablePath == JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS) return null; // break cycle (initializer did not init or reentering call)
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_variable_value_after_initialization(variableName, variablePath);
+ manager.variablesWithInitializer.add(variableName);
+ ok = true;
+ } catch (RuntimeException e) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ e.printStackTrace();
+ throw e;
+ } catch (Error e) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ e.printStackTrace();
+ throw e;
+ } finally {
+ if (!ok) JavaModelManager.getJavaModelManager().variablePut(variableName, null); // flush cache
+ }
+ } else {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_no_variable_initializer_found(variableName);
+ }
+ return variablePath;
+ }
+
+ private static void verbose_no_variable_initializer_found(String variableName) {
+ Util.verbose(
+ "CPVariable INIT - no initializer found\n" + //$NON-NLS-1$
+ " variable: " + variableName); //$NON-NLS-1$
+ }
+
+ private static void verbose_variable_value_after_initialization(String variableName, IPath variablePath) {
+ Util.verbose(
+ "CPVariable INIT - after initialization\n" + //$NON-NLS-1$
+ " variable: " + variableName +'\n' + //$NON-NLS-1$
+ " variable path: " + variablePath); //$NON-NLS-1$
+ }
+
+ private static void verbose_triggering_variable_initialization(String variableName, JsGlobalScopeVariableInitializer initializer) {
+ Util.verbose(
+ "CPVariable INIT - triggering initialization\n" + //$NON-NLS-1$
+ " variable: " + variableName + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+ }
+
+ private static void verbose_triggering_variable_initialization_invocation_trace() {
+ Util.verbose(
+ "CPVariable INIT - triggering initialization\n" + //$NON-NLS-1$
+ " invocation trace:"); //$NON-NLS-1$
+ new Exception("null
otherwise.
+ */
+ public static String getIncludepathVariableDeprecationMessage(String variableName) {
+ return (String) JavaModelManager.getJavaModelManager().deprecatedVariables.get(variableName);
+ }
+
+ /**
+ * Helper method finding the includepath variable initializer registered for a given includepath variable name
+ * or null
if none was found while iterating over the contributions to extension point to
+ * the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeVariableInitializer".
+ * null
if
+ * none was found.
+ */
+ public static JsGlobalScopeVariableInitializer getJsGlobalScopeVariableInitializer(String variable){
+
+ Plugin jdtCorePlugin = JavaScriptCore.getPlugin();
+ if (jdtCorePlugin == null) return null;
+
+ IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaScriptCore.PLUGIN_ID, JavaModelManager.CPVARIABLE_INITIALIZER_EXTPOINT_ID);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for(int i = 0; i < extensions.length; i++){
+ IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
+ for(int j = 0; j < configElements.length; j++){
+ IConfigurationElement configElement = configElements[j];
+ try {
+ String varAttribute = configElement.getAttribute("variable"); //$NON-NLS-1$
+ if (variable.equals(varAttribute)) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_found_variable_initializer(variable, configElement);
+ Object execExt = configElement.createExecutableExtension("class"); //$NON-NLS-1$
+ if (execExt instanceof JsGlobalScopeVariableInitializer){
+ JsGlobalScopeVariableInitializer initializer = (JsGlobalScopeVariableInitializer)execExt;
+ String deprecatedAttribute = configElement.getAttribute("deprecated"); //$NON-NLS-1$
+ if (deprecatedAttribute != null) {
+ JavaModelManager.getJavaModelManager().deprecatedVariables.put(variable, deprecatedAttribute);
+ }
+ String readOnlyAttribute = configElement.getAttribute("readOnly"); //$NON-NLS-1$
+ if (JavaModelManager.TRUE.equals(readOnlyAttribute)) {
+ JavaModelManager.getJavaModelManager().readOnlyVariables.add(variable);
+ }
+ return initializer;
+ }
+ }
+ } catch(CoreException e){
+ // executable extension could not be created: ignore this initializer
+ if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ verbose_failed_to_instanciate_variable_initializer(variable, configElement);
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static void verbose_failed_to_instanciate_variable_initializer(String variable, IConfigurationElement configElement) {
+ Util.verbose(
+ "CPContainer INIT - failed to instanciate initializer\n" + //$NON-NLS-1$
+ " variable: " + variable + '\n' + //$NON-NLS-1$
+ " class: " + configElement.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$
+ System.err);
+ }
+
+ private static void verbose_found_variable_initializer(String variable, IConfigurationElement configElement) {
+ Util.verbose(
+ "CPVariable INIT - found initializer\n" + //$NON-NLS-1$
+ " variable: " + variable + '\n' + //$NON-NLS-1$
+ " class: " + configElement.getAttribute("class")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Returns the names of all known includepath variables.
+ * setOptions
.
+ *
+ * Helper constants have been defined on JavaScriptCore for each of the option ID and
+ * their possible constant values.
+ *
+ * Note: more options might be added in further releases.
+ *
+ * RECOGNIZED OPTIONS:
+ *
+ * VALIDATOR / Setting Compliance Level
+ * Select the compliance level for the validator. In "1.3" mode, source and target settings
+ * should not go beyond "1.3" level.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.compliance"
+ * - possible values: { "1.3", "1.4", "1.5", "1.6", "1.7" }
+ * - default: "1.4"
+ *
+ * VALIDATOR / Setting Source Compatibility Mode
+ * Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword
+ * reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
+ * level should be set to "1.4" and the compliance mode should be "1.4".
+ * Source level 1.5 is necessary to enable generics, autoboxing, covariance, annotations, enumerations
+ * enhanced for loop, static imports and varargs. Once toggled, the target VM level should be set to "1.5"
+ * and the compliance mode should be "1.5".
+ * Source level 1.6 is necessary to enable the computation of stack map tables. Once toggled, the target
+ * VM level should be set to "1.6" and the compliance mode should be "1.6".
+ * Once the source level 1.7 is toggled, the target VM level should be set to "1.7" and the compliance mode
+ * should be "1.7".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.source"
+ * - possible values: { "1.3", "1.4", "1.5", "1.6", "1.7" }
+ * - default: "1.3"
+ *
+ *
+ * VALIDATOR / JSdoc Comment Support
+ * When this support is disabled, the validator will ignore all jsdoc problems options settings
+ * and will not report any jsdoc problem. It will also not find any reference in jsdoc comment and
+ * DOM AST JSdoc node will be only a flat text instead of having structured tag elements.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.doc.comment.support"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * VALIDATOR / Reporting Deprecation
+ * When enabled, the validator will signal use of deprecated API either as an
+ * error or a warning.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.deprecation"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Deprecation Inside Deprecated Code
+ * When enabled, the validator will signal use of deprecated API inside deprecated code.
+ * The severity of the problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.deprecation".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.deprecationInDeprecatedCode"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Deprecation When Overriding Deprecated Method
+ * When enabled, the validator will signal the declaration of a method overriding a deprecated one.
+ * The severity of the problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.deprecation".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Unused Local
+ * When enabled, the validator will issue an error or a warning for unused local
+ * variables (that is, variables never read from)
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedLocal"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Unused Parameter
+ * When enabled, the validator will issue an error or a warning for unused method
+ * parameters (that is, parameters never read from)
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Unused Parameter if Implementing Abstract Method
+ * When enabled, the validator will signal unused parameters in abstract method implementations.
+ * The severity of the problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Unused Parameter if Overriding Concrete Method
+ * When enabled, the validator will signal unused parameters in methods overriding concrete ones.
+ * The severity of the problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenOverridingConcrete"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Consider Reference in Doc Comment for Unused Parameter Check
+ * When enabled, the validator will consider doc comment references to parameters (i.e. @param clauses) for the unused
+ * parameter check. Thus, documented parameters will be considered as mandated as per doc contract.
+ * The severity of the unused parameter problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter".
+ * Note: this option has no effect until the doc comment support is enabled according to the
+ * option "org.eclipse.wst.jsdt.core.compiler.doc.comment.support".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocReference"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * VALIDATOR / Reporting Unused Import
+ * When enabled, the validator will issue an error or a warning for unused import
+ * reference
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedImport"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Unused Private Members
+ * When enabled, the validator will issue an error or a warning whenever a private
+ * method or field is declared but never used within the same unit.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Assignment with no Effect
+ * When enabled, the validator will issue an error or a warning whenever an assignment
+ * has no effect (e.g 'x = x').
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.noEffectAssignment"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Empty Statements and Unnecessary Semicolons
+ * When enabled, the validator will issue an error or a warning if an empty statement or a
+ * unnecessary semicolon is encountered.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.emptyStatement"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Unnecessary Type Check
+ * When enabled, the validator will issue an error or a warning when a cast or an instanceof operation
+ * is unnecessary.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryTypeCheck"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Unnecessary Else
+ * When enabled, the validator will issue an error or a warning when a statement is unnecessarily
+ * nested within an else clause (in situation where then clause is not completing normally).
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryElse"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Non-Externalized String Literal
+ * When enabled, the validator will issue an error or a warning for non externalized
+ * String literal (that is, not tagged with //$NON-NLS-<n>$).
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.nonExternalizedStringLiteral"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Non-Static Reference to a Static Member
+ * When enabled, the validator will issue an error or a warning whenever a static field
+ * or method is accessed with an expression receiver. A reference to a static member should
+ * be qualified with a type name.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.staticAccessReceiver"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Indirect Reference to a Static Member
+ * When enabled, the validator will issue an error or a warning whenever a static field
+ * or method is accessed in an indirect way. A reference to a static member should
+ * preferably be qualified with its declaring type name.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.indirectStaticAccess"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Local Variable Declaration Hiding another Variable
+ * When enabled, the validator will issue an error or a warning whenever a local variable
+ * declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.localVariableHiding"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Field Declaration Hiding another Variable
+ * When enabled, the validator will issue an error or a warning whenever a field
+ * declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.fieldHiding"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Type Declaration Hiding another Type
+ * When enabled, the validator will issue an error or a warning in situations where a type parameter
+ * declaration is hiding some type, when a nested type is hiding some type parameter, or when
+ * a nested type is hiding another nested type defined in same unit.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.typeParameterHiding"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Possible Accidental Boolean Assignment
+ * When enabled, the validator will issue an error or a warning if a boolean assignment is acting as the condition
+ * of a control statement (where it probably was meant to be a boolean comparison).
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.possibleAccidentalBooleanAssignment"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Undocumented Empty Block
+ * When enabled, the validator will issue an error or a warning when an empty block is detected and it is not
+ * documented with any comment.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.undocumentedEmptyBlock"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Finally Blocks Not Completing Normally
+ * When enabled, the validator will issue an error or a warning when a finally block does not complete normally.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.finallyBlockNotCompletingNormally"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Unused Declared Thrown Exception
+ * When enabled, the validator will issue an error or a warning when a method or a constructor is declaring a
+ * thrown checked exception, but never actually raises it in its body.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownException"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Unused Declared Thrown Exception in Overridind Method
+ * When disabled, the validator will not include overriding methods in its diagnosis for unused declared
+ * thrown exceptions.
+ *
+ */
+ public static Hashtable getDefaultOptions(){
+ return JavaModelManager.getJavaModelManager().getDefaultOptions();
+ }
+
+ /**
+ * Returns the workspace root default charset encoding.
+ *
+ * @return the name of the default charset encoding for workspace root.
+ * @see IContainer#getDefaultCharset()
+ * @see ResourcesPlugin#getEncoding()
+ */
+ public static String getEncoding() {
+ // Verify that workspace is not shutting down (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=60687)
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ if (workspace != null) {
+ try {
+ return workspace.getRoot().getDefaultCharset();
+ } catch (CoreException e) {
+ // fails silently and return plugin global encoding if core exception occurs
+ }
+ }
+ return ResourcesPlugin.getEncoding();
+ }
+
+ /**
+ * Returns an array that contains the resources generated by the JavaScript builder when building the
+ * javaScript units contained in the given region.
+ *
+ * The severity of the problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownException".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Unqualified Access to Field
+ * When enabled, the validator will issue an error or a warning when a field is access without any qualification.
+ * In order to improve code readability, it should be qualified, e.g. 'x' should rather be written 'this.x'.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unqualifiedFieldAccess"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Null Dereference
+ * When enabled, the validator will issue an error or a warning whenever a
+ * variable that is statically known to hold a null value is used to
+ * access a field or method.
+ *
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.nullReference"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Potential Null Dereference
+ * When enabled, the validator will issue an error or a warning whenever a
+ * variable that has formerly been tested against null but is not (no more)
+ * statically known to hold a non-null value is used to access a field or
+ * method.
+ *
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.potentialNullReference"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Duplicate Local Variables
+ * When enabled, the validator will issue an error or a warning whenever a
+ * two local variables with the same name have been declared.
+ *
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.duplicateLocalVariables"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Redundant Null Check
+ * When enabled, the validator will issue an error or a warning whenever a
+ * variable that is statically known to hold a null or a non-null value
+ * is tested against null.
+ *
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.redundantNullCheck"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Use of Annotation Type as Super Interface
+ * When enabled, the validator will issue an error or a warning whenever an annotation type is used
+ * as a super-interface. Though legal, this is discouraged.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.annotationSuperInterface"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Invalid Jsdoc Comment
+ * This is the generic control for the severity of JSdoc problems.
+ * When enabled, the validator will issue an error or a warning for a problem in JSdoc.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadoc"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Visibility Level For Invalid JSdoc Tags
+ * Set the minimum visibility level for JSdoc tag problems. Below this level problems will be ignored.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTagsVisibility"
+ * - possible values: { "public", "protected", "default", "private" }
+ * - default: "public"
+ *
+ * VALIDATOR / Reporting Invalid JSdoc Tags
+ * When enabled, the validator will signal unbound or unexpected reference tags in JSdoc.
+ * A 'throws' tag referencing an undeclared exception would be considered as unexpected.
+ *
Note that this diagnosis can be enabled based on the visibility of the construct associated with the JSDoc;
+ * also see the setting "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTagsVisibility".
+ *
+ * The severity of the problem is controlled with option "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadoc".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTags"
+ * - possible values: { "disabled", "enabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Invalid JSdoc Tags with Deprecated References
+ * Specify whether the validator will report deprecated references used in JSdoc tags.
+ *
Note that this diagnosis can be enabled based on the visibility of the construct associated with the JSDoc;
+ * also see the setting "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTagsVisibility".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Invalid JSdoc Tags with Not Visible References
+ * Specify whether the validator will report non-visible references used in JSDoc tags.
+ *
Note that this diagnosis can be enabled based on the visibility of the construct associated with the JSDoc;
+ * also see the setting "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTagsVisibility".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Missing JSDoc Tags
+ * This is the generic control for the severity of JSDoc missing tag problems.
+ * When enabled, the validator will issue an error or a warning when tags are missing in JSDoc comments.
+ *
Note that this diagnosis can be enabled based on the visibility of the construct associated with the JSDoc;
+ * also see the setting "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocTagsVisibility".
+ *
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocTags"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Visibility Level For Missing JSDoc Tags
+ * Set the minimum visibility level for JSDoc missing tag problems. Below this level problems will be ignored.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocTagsVisibility"
+ * - possible values: { "public", "protected", "default", "private" }
+ * - default: "public"
+ *
+ * VALIDATOR / Reporting Missing JSDoc Tags on Overriding Methods
+ * Specify whether the validator will verify overriding methods in order to report JSDoc missing tag problems.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocTagsOverriding"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Reporting Missing JSDoc Comments
+ * This is the generic control for the severity of missing JSDoc comment problems.
+ * When enabled, the validator will issue an error or a warning when JSDoc comments are missing.
+ *
Note that this diagnosis can be enabled based on the visibility of the construct associated with the expected JSDoc;
+ * also see the setting "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocCommentsVisibility".
+ *
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocComments"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Visibility Level For Missing JSDoc Comments
+ * Set the minimum visibility level for missing JSDoc problems. Below this level problems will be ignored.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocCommentsVisibility"
+ * - possible values: { "public", "protected", "default", "private" }
+ * - default: "public"
+ *
+ * VALIDATOR / Reporting Missing JSDoc Comments on Overriding Methods
+ * Specify whether the validator will verify overriding methods in order to report missing JSDoc comment problems.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.missingJavadocCommentsOverriding"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * VALIDATOR / Maximum Number of Problems Reported per JavaScript Unit
+ * Specify the maximum number of problems reported on each javaScript unit.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.maxProblemPerUnit"
+ * - possible values: "<n>" where <n> is zero or a positive integer (if zero then all problems are reported).
+ * - default: "100"
+ *
+ * VALIDATOR / Treating Optional Error as Fatal
+ * When enabled, optional errors (i.e. optional problems which severity is set to "error") will be treated as standard
+ * validator errors, yielding problem methods/types preventing from running offending code until the issue got resolved.
+ * When disabled, optional errors are only considered as warnings, still carrying an error indication to make them more
+ * severe. Note that by default, errors are fatal, whether they are optional or not.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.fatalOptionalError"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * VALIDATOR / Defining the Automatic Task Tags
+ * When the tag list is not empty, the validator will issue a task marker whenever it encounters
+ * one of the corresponding tags inside any comment in JavaScript source code.
+ * Generated task messages will start with the tag, and range until the next line separator,
+ * comment ending, or tag.
+ * When a given line of code bears multiple tags, each tag will be reported separately.
+ * Moreover, a tag immediately followed by another tag will be reported using the contents of the
+ * next non-empty tag of the line, if any.
+ * Note that tasks messages are trimmed. If a tag is starting with a letter or digit, then it cannot be leaded by
+ * another letter or digit to be recognized ("fooToDo" will not be recognized as a task for tag "ToDo", but "foo#ToDo"
+ * will be detected for either tag "ToDo" or "#ToDo"). Respectively, a tag ending with a letter or digit cannot be followed
+ * by a letter or digit to be recognized ("ToDofoo" will not be recognized as a task for tag "ToDo", but "ToDo:foo" will
+ * be detected either for tag "ToDo" or "ToDo:").
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.taskTags"
+ * - possible values: { "<tag>[,<tag>]*" } where <tag> is a String without any wild-card or leading/trailing spaces
+ * - default: "TODO,FIXME,XXX"
+ *
+ * VALIDATOR / Defining the Automatic Task Priorities
+ * In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
+ * of the task markers issued by the validator.
+ * If the default is specified, the priority of each task marker is "NORMAL".
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.taskPriorities"
+ * - possible values: { "<priority>[,<priority>]*" } where <priority> is one of "HIGH", "NORMAL" or "LOW"
+ * - default: "NORMAL,HIGH,NORMAL"
+ *
+ * VALIDATOR / Determining whether task tags are case-sensitive
+ * When enabled, task tags are considered in a case-sensitive way.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.taskCaseSensitive"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * VALIDATOR / Reporting Discouraged Reference to Type with Restricted Access
+ * When enabled, the validator will issue an error or a warning when referring to a type with discouraged access, as defined according
+ * to the access rule specifications.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.discouragedReference"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Unreferenced Label
+ * When enabled, the validator will issue an error or a warning when encountering a labeled statement which label
+ * is never explicitly referenced. A label is considered to be referenced if its name explicitly appears behind a break
+ * or continue statement; for instance the following label would be considered unreferenced; LABEL: { break; }
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.unusedLabel"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * VALIDATOR / Reporting Parameter Assignment
+ * When enabled, the validator will issue an error or a warning if a parameter is
+ * assigned to.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.parameterAssignment"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Switch Fall-Through Case
+ * When enabled, the validator will issue an error or a warning if a case may be
+ * entered by falling through previous case. Empty cases are allowed.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.fallthroughCase"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * VALIDATOR / Reporting Overriding method that doesn't call the super method invocation
+ * When enabled, the validator will issue an error or a warning if a method is overriding a method without calling
+ * the super invocation.
+ * - option id: "org.eclipse.wst.jsdt.core.compiler.problem.overridingMethodWithoutSuperInvocation"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * BUILDER / Specifying Filters for Resource Copying Control
+ * Allow to specify some filters to control the resource copy process.
+ * - option id: "org.eclipse.wst.jsdt.core.builder.resourceCopyExclusionFilter"
+ * - possible values: { "<name>[,<name>]* } where <name> is a file name pattern (* and ? wild-cards allowed)
+ * or the name of a folder which ends with '/'
+ * - default: ""
+ *
+ * BUILDER / Abort if Invalid Includepath
+ * Allow to toggle the builder to abort if the includepath is invalid
+ * - option id: "org.eclipse.wst.jsdt.core.builder.invalidClasspath"
+ * - possible values: { "abort", "ignore" }
+ * - default: "abort"
+ *
+ * BUILDER / Reporting Duplicate Resources
+ * Indicate the severity of the problem reported when more than one occurrence
+ * of a resource is to be copied into the output location.
+ * - option id: "org.eclipse.wst.jsdt.core.builder.duplicateResourceTask"
+ * - possible values: { "error", "warning" }
+ * - default: "warning"
+ *
+ * JAVACORE / Computing Project Build Order
+ * Indicate whether JavaScriptCore should enforce the project build order to be based on
+ * the includepath prerequisite chain. When requesting to compute, this takes over
+ * the platform default order (based on project references).
+ * - option id: "org.eclipse.wst.jsdt.core.computeJavaBuildOrder"
+ * - possible values: { "compute", "ignore" }
+ * - default: "ignore"
+ *
+ * JAVACORE / Default Source Encoding Format
+ * Get the default encoding format of source files. This value is
+ * immutable and preset to the result of ResourcesPlugin.getEncoding().
+ * It is offered as a convenience shortcut only.
+ * - option id: "org.eclipse.wst.jsdt.core.encoding"
+ * - value: <immutable, platform default value>
+ *
+ * JAVACORE / Reporting Incomplete Includepath
+ * Indicate the severity of the problem reported when an entry on the includepath does not exist,
+ * is not legite or is not visible (for example, a referenced project is closed).
+ * - option id: "org.eclipse.wst.jsdt.core.incompleteClasspath"
+ * - possible values: { "error", "warning"}
+ * - default: "error"
+ *
+ * JAVACORE / Reporting Includepath Cycle
+ * Indicate the severity of the problem reported when a project is involved in a cycle.
+ * - option id: "org.eclipse.wst.jsdt.core.circularClasspath"
+ * - possible values: { "error", "warning" }
+ * - default: "error"
+ * JAVACORE / Enabling Usage of Includepath Exclusion Patterns
+ * When disabled, no entry on a project includepath can be associated with
+ * an exclusion pattern.
+ * - option id: "org.eclipse.wst.jsdt.core.includepath.exclusionPatterns"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * JAVACORE / Enabling Usage of Includepath Multiple Output Locations
+ * When disabled, no entry on a project includepath can be associated with
+ * a specific output location, preventing thus usage of multiple output locations.
+ * - option id: "org.eclipse.wst.jsdt.core.includepath.multipleOutputLocations"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * JAVACORE / Set the timeout value for retrieving the method's parameter names from jsdoc
+ * Timeout in milliseconds to retrieve the method's parameter names from jsdoc.
+ * If the value is 0, the parameter names are not fetched and the raw names are returned.
+ * - option id: "org.eclipse.wst.jsdt.core.timeoutForParameterNameFromAttachedJavadoc"
+ * - possible values: "<n>", where n is an integer greater than or equal to 0
+ * - default: "50"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: FORMATTER / Inserting New Line Before Opening Brace
+ * When Insert, a new line is inserted before an opening brace, otherwise nothing
+ * is inserted
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.newline.openingBrace"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "do not insert"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: FORMATTER / Inserting New Line Inside Control Statement
+ * When Insert, a new line is inserted between } and following else, catch, finally
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.newline.controlStatement"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "do not insert"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Clearing Blank Lines
+ * When Clear all, all blank lines are removed. When Preserve one, only one is kept
+ * and all others removed.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.newline.clearAll"
+ * - possible values: { "clear all", "preserve one" }
+ * - default: "preserve one"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Inserting New Line Between Else/If
+ * When Insert, a blank line is inserted between an else and an if when they are
+ * contiguous. When choosing to not insert, else-if will be kept on the same
+ * line when possible.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.newline.elseIf"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "do not insert"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Inserting New Line In Empty Block
+ * When insert, a line break is inserted between contiguous { and }, if } is not followed
+ * by a keyword.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.newline.emptyBlock"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "insert"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Splitting Lines Exceeding Length
+ * Enable splitting of long lines (exceeding the configurable length). Length of 0 will
+ * disable line splitting
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.lineSplit"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "80"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Compacting Assignment
+ * Assignments can be formatted asymmetrically, for example 'int x= 2;', when Normal, a space
+ * is inserted before the assignment operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.style.assignment"
+ * - possible values: { "compact", "normal" }
+ * - default: "normal"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Defining Indentation Character
+ * Either choose to indent with tab characters or spaces
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.tabulation.char"
+ * - possible values: { "tab", "space" }
+ * - default: "tab"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Defining Space Indentation Length
+ * When using spaces, set the amount of space characters to use for each
+ * indentation mark.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.tabulation.size"
+ * - possible values: "<n>", where n is a positive integer
+ * - default: "4"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Inserting space in cast expression
+ * When Insert, a space is added between the type and the expression in a cast expression.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.space.castexpression"
+ * - possible values: { "insert", "do not insert" }
+ * - default: "insert"
+ *
+ * CODEASSIST / Activate Visibility Sensitive Completion
+ * When active, completion doesn't show that you can not see
+ * (for example, you can not see private methods of a super class).
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.visibilityCheck"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Activate Deprecation Sensitive Completion
+ * When enabled, completion doesn't propose deprecated members and types.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.deprecationCheck"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Automatic Qualification of Implicit Members
+ * When active, completion automatically qualifies completion on implicit
+ * field references and message expressions.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.forceImplicitQualification"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Define the Prefixes for Field Name
+ * When the prefixes is non empty, completion for field name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.fieldPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Prefixes for Static Field Name
+ * When the prefixes is non empty, completion for static field name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.staticFieldPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Prefixes for Local Variable Name
+ * When the prefixes is non empty, completion for local variable name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.localPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Prefixes for Argument Name
+ * When the prefixes is non empty, completion for argument name will begin with
+ * one of the proposed prefixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.argumentPrefixes"
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Field Name
+ * When the suffixes is non empty, completion for field name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.fieldSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Static Field Name
+ * When the suffixes is non empty, completion for static field name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.staticFieldSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Local Variable Name
+ * When the suffixes is non empty, completion for local variable name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.localSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Define the Suffixes for Argument Name
+ * When the suffixes is non empty, completion for argument name will end with
+ * one of the proposed suffixes.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.argumentSuffixes"
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - default: ""
+ *
+ * CODEASSIST / Activate Forbidden Reference Sensitive Completion
+ * When enabled, completion doesn't propose elements which match a
+ * forbidden reference rule.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.forbiddenReferenceCheck"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * CODEASSIST / Activate Discouraged Reference Sensitive Completion
+ * When enabled, completion doesn't propose elements which match a
+ * discouraged reference rule.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.discouragedReferenceCheck"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Activate Camel Case Sensitive Completion
+ * When enabled, completion shows proposals whose name match the CamelCase
+ * pattern.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.camelCaseMatch"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * CODEASSIST / Activate Suggestion of Static Import
+ * When enabled, completion proposals can contain static import
+ * pattern.
+ * - option id: "org.eclipse.wst.jsdt.core.codeComplete.suggestStaticImports"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ *
+ * org.eclipse.wst.jsdt.core.IJavaScriptUnit
org.eclipse.wst.jsdt.core.IPackageFragment
org.eclipse.wst.jsdt.core.IPackageFragmentRoot
org.eclipse.wst.jsdt.core.IJavaScriptProject
org.eclipse.wst.jsdt.core.IJavaScriptElement
are ignored.null
+ */
+ public static IResource[] getGeneratedResources(IRegion region, boolean includesNonJavaResources) {
+ if (region == null) throw new IllegalArgumentException("region cannot be null"); //$NON-NLS-1$
+ IJavaScriptElement[] elements = region.getElements();
+ HashMap projectsStates = new HashMap();
+ ArrayList collector = new ArrayList();
+ for (int i = 0, max = elements.length; i < max; i++) {
+ // collect all the javaScript project
+ IJavaScriptElement element = elements[i];
+ IJavaScriptProject javaProject = element.getJavaScriptProject();
+ IProject project = javaProject.getProject();
+ State state = null;
+ State currentState = (State) projectsStates.get(project);
+ if (currentState != null) {
+ state = currentState;
+ } else {
+ state = (State) JavaModelManager.getJavaModelManager().getLastBuiltState(project, null);
+ if (state != null) {
+ projectsStates.put(project, state);
+ }
+ }
+ if (state == null) continue;
+ if (element.getElementType() == IJavaScriptElement.JAVASCRIPT_PROJECT) {
+ IPackageFragmentRoot[] roots = null;
+ try {
+ roots = javaProject.getPackageFragmentRoots();
+ } catch (JavaScriptModelException e) {
+ // ignore
+ }
+ if (roots == null) continue;
+ IRegion region2 = JavaScriptCore.newRegion();
+ for (int j = 0; j < roots.length; j++) {
+ region2.add(roots[j]);
+ }
+ IResource[] res = getGeneratedResources(region2, includesNonJavaResources);
+ for (int j = 0, max2 = res.length; j < max2; j++) {
+ collector.add(res[j]);
+ }
+ continue;
+ }
+
+ IJavaScriptElement root = element;
+ while (root != null && root.getElementType() != IJavaScriptElement.PACKAGE_FRAGMENT_ROOT) {
+ root = root.getParent();
+ }
+ if (root == null) continue;
+ }
+ int size = collector.size();
+ if (size != 0) {
+ IResource[] result = new IResource[size];
+ collector.toArray(result);
+ return result;
+ }
+ return NO_GENERATED_RESOURCES;
+ }
+
+ /**
+ * Returns the single instance of the JavaScript core plug-in runtime class.
+ * Equivalent to (JavaScriptCore) getPlugin()
.
+ *
+ * @return the single instance of the JavaScript core plug-in runtime class
+ */
+ public static JavaScriptCore getJavaScriptCore() {
+ return (JavaScriptCore) getPlugin();
+ }
+
+ /**
+ * Returns the list of known JavaScript-like extensions.
+ * JavaScript like extension are defined in the {@link org.eclipse.core.runtime.Platform#getContentTypeManager()
+ * content type manager} for the {@link #JAVA_SOURCE_CONTENT_TYPE}.
+ * Note that a JavaScript-like extension doesn't include the leading dot ('.').
+ * Also note that the "js" extension is always defined as a JavaScript-like extension.
+ *
+ * @return the list of known JavaScript-like extensions.
+ */
+ public static String[] getJavaScriptLikeExtensions() {
+ return CharOperation.toStrings(Util.getJavaLikeExtensions());
+ }
+
+ /**
+ * Helper method for returning one option value only. Equivalent to (String)JavaScriptCore.getOptions().get(optionName)
+ * Note that it may answer null
if this option does not exist.
+ * getDefaultOptions
.
+ * getDefaultOptions
.String
; value type: String
)
+ * @see #getDefaultOptions()
+ * @see org.eclipse.wst.jsdt.internal.core.JavaCorePreferenceInitializer for changing default settings
+ */
+ public static Hashtable getOptions() {
+ return JavaModelManager.getJavaModelManager().getOptions();
+ }
+
+ /**
+ * Returns the single instance of the JavaScript core plug-in runtime class.
+ *
+ * @return the single instance of the JavaScript core plug-in runtime class
+ */
+ public static Plugin getPlugin() {
+ return JAVA_CORE_PLUGIN;
+ }
+
+ /**
+ * This is a helper method, which returns the resolved includepath entry denoted
+ * by a given entry (if it is a variable entry). It is obtained by resolving the variable
+ * reference in the first segment. Returns null
if unable to resolve using
+ * the following algorithm:
+ *
+ *
+ * null
null
JavaScriptCore#getJsGlobalScopeContainer(IPath, IJavaScriptProject)
.
+ * null
+ * if the given variable entry could not be resolved to a valid includepath entry
+ */
+ public static IIncludePathEntry getResolvedIncludepathEntry(IIncludePathEntry entry) {
+
+ if (entry.getEntryKind() != IIncludePathEntry.CPE_VARIABLE)
+ return entry;
+
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IPath resolvedPath = JavaScriptCore.getResolvedVariablePath(entry.getPath());
+ if (resolvedPath == null)
+ return null;
+
+ Object target = JavaModel.getTarget(workspaceRoot, resolvedPath, false);
+ if (target == null)
+ return null;
+
+ // inside the workspace
+ if (target instanceof IResource) {
+ IResource resolvedResource = (IResource) target;
+ switch (resolvedResource.getType()) {
+
+ case IResource.PROJECT :
+ // internal project
+ return JavaScriptCore.newProjectEntry(
+ resolvedPath,
+ entry.getAccessRules(),
+ entry.combineAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
+ case IResource.FILE :
+ if (org.eclipse.wst.jsdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) {
+ // internal binary archive
+ return JavaScriptCore.newLibraryEntry(
+ resolvedPath,
+ getResolvedVariablePath(entry.getSourceAttachmentPath()),
+ getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+ entry.getAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
+ }
+ break;
+
+ case IResource.FOLDER :
+ // internal binary folder
+ return JavaScriptCore.newLibraryEntry(
+ resolvedPath,
+ getResolvedVariablePath(entry.getSourceAttachmentPath()),
+ getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+ entry.getAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
+ }
+ }
+ // outside the workspace
+ if (target instanceof File) {
+ File externalFile = JavaModel.getFile(target);
+ if (externalFile != null) {
+ String fileName = externalFile.getName().toLowerCase();
+ if (fileName.endsWith(SuffixConstants.SUFFIX_STRING_java)
+ || fileName.endsWith(SuffixConstants.SUFFIX_STRING_zip)
+ ) {
+ // external binary archive
+ return JavaScriptCore.newLibraryEntry(
+ resolvedPath,
+ getResolvedVariablePath(entry.getSourceAttachmentPath()),
+ getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+ entry.getAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
+ }
+ } else { // external binary folder
+ if (resolvedPath.isAbsolute()){
+ return JavaScriptCore.newLibraryEntry(
+ resolvedPath,
+ getResolvedVariablePath(entry.getSourceAttachmentPath()),
+ getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+ entry.getAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
+ }
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Resolve a variable path (helper method).
+ *
+ * @param variablePath the given variable path
+ * @return the resolved variable path or null
if none
+ */
+ public static IPath getResolvedVariablePath(IPath variablePath) {
+
+ if (variablePath == null)
+ return null;
+ int count = variablePath.segmentCount();
+ if (count == 0)
+ return null;
+
+ // lookup variable
+ String variableName = variablePath.segment(0);
+ IPath resolvedPath = JavaScriptCore.getIncludepathVariable(variableName);
+ if (resolvedPath == null)
+ return null;
+
+ // append path suffix
+ if (count > 1) {
+ resolvedPath = resolvedPath.append(variablePath.removeFirstSegments(1));
+ }
+ return resolvedPath;
+ }
+
+ /**
+ * Returns the names of all defined user libraries. The corresponding includepath container path
+ * is the name appended to the USER_LIBRARY_CONTAINER_ID.
+ * @return Return an array containing the names of all known user defined.
+ */
+ public static String[] getUserLibraryNames() {
+ return UserLibraryManager.getUserLibraryNames();
+ }
+
+ /**
+ * Returns the working copies that have the given owner.
+ * Only javaScript units in working copy mode are returned.
+ * If the owner is null
, primary working copies are returned.
+ *
+ * @param owner the given working copy owner or null
for primary working copy owner
+ * @return the list of working copies for a given owner
+ */
+ public static IJavaScriptUnit[] getWorkingCopies(WorkingCopyOwner owner){
+
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ if (owner == null) owner = DefaultWorkingCopyOwner.PRIMARY;
+ IJavaScriptUnit[] result = manager.getWorkingCopies(owner, false/*don't add primary WCs*/);
+ if (result == null) return JavaModelManager.NO_WORKING_COPY;
+ return result;
+ }
+
+ /**
+ * Initializes JavaScriptCore internal structures to allow subsequent operations (such
+ * as the ones that need a resolved classpath) to run full speed. A client may
+ * choose to call this method in a background thread early after the workspace
+ * has started so that the initialization is transparent to the user.
+ * null
if progress
+ * reporting and cancellation are not desired
+ * @exception CoreException if the initialization fails,
+ * the status of the exception indicates the reason of the failure
+ */
+ public static void initializeAfterLoad(IProgressMonitor monitor) throws CoreException {
+ try {
+ if (monitor != null) monitor.beginTask(Messages.javamodel_initialization, 100);
+
+ // initialize all containers and variables
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ try {
+ if (monitor != null) {
+ monitor.subTask(Messages.javamodel_configuring_classpath_containers);
+ manager.batchContainerInitializationsProgress.set(new SubProgressMonitor(monitor, 50)); // 50% of the time is spent in initializing containers and variables
+ }
+
+ // all classpaths in the workspace are going to be resolved, ensure that containers are initialized in one batch
+ manager.batchContainerInitializations = true;
+
+ // avoid leaking source attachment properties (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183413)
+ IJavaScriptProject[] projects = manager.getJavaModel().getJavaScriptProjects();
+ for (int i = 0, length = projects.length; i < length; i++) {
+ IIncludePathEntry[] classpath;
+ try {
+ classpath = ((JavaProject) projects[i]).getResolvedClasspath();
+ } catch (JavaScriptModelException e) {
+ // project no longer exist: ignore
+ continue;
+ }
+ if (classpath != null) {
+ for (int j = 0, length2 = classpath.length; j < length2; j++) {
+ IIncludePathEntry entry = classpath[j];
+ if (entry.getSourceAttachmentPath() != null)
+ Util.setSourceAttachmentProperty(entry.getPath(), null);
+ // else source might have been attached by IPackageFragmentRoot#attachSource(...), we keep it
+ }
+ }
+ }
+
+ // initialize delta state
+ manager.deltaState.rootsAreStale = true; // in case it was already initialized before we cleaned up the source attachment proprties
+ manager.deltaState.initializeRoots();
+ } finally {
+ manager.batchContainerInitializationsProgress.set(null);
+ }
+
+ // dummy query for waiting until the indexes are ready
+ SearchEngine engine = new SearchEngine();
+ IJavaScriptSearchScope scope = SearchEngine.createWorkspaceScope();
+ try {
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_configuring_searchengine);
+ engine.searchAllTypeNames(
+ null,
+ SearchPattern.R_EXACT_MATCH,
+ "!@$#!@".toCharArray(), //$NON-NLS-1$
+ SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
+ IJavaScriptSearchConstants.CLASS,
+ scope,
+ new TypeNameRequestor() {
+ public void acceptType(
+ int modifiers,
+ char[] packageName,
+ char[] simpleTypeName,
+ char[][] enclosingTypeNames,
+ String path) {
+ // no type to accept
+ }
+ },
+ // will not activate index query caches if indexes are not ready, since it would take to long
+ // to wait until indexes are fully rebuild
+ IJavaScriptSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
+ monitor == null ? null : new SubProgressMonitor(monitor, 49) // 49% of the time is spent in the dummy search
+ );
+ } catch (JavaScriptModelException e) {
+ // /search failed: ignore
+ } catch (OperationCanceledException e) {
+ if (monitor != null && monitor.isCanceled())
+ throw e;
+ // else indexes were not ready: catch the exception so that jars are still refreshed
+ }
+
+ // check if the build state version number has changed since last session
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=98969)
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_getting_build_state_number);
+ QualifiedName qName = new QualifiedName(JavaScriptCore.PLUGIN_ID, "stateVersionNumber"); //$NON-NLS-1$
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ String versionNumber = null;
+ try {
+ versionNumber = root.getPersistentProperty(qName);
+ } catch (CoreException e) {
+ // could not read version number: consider it is new
+ }
+ final JavaModel model = manager.getJavaModel();
+ String newVersionNumber = Byte.toString(State.VERSION);
+ if (!newVersionNumber.equals(versionNumber)) {
+ // build state version number has changed: touch every projects to force a rebuild
+ if (JavaBuilder.DEBUG)
+ System.out.println("Build state version number has changed"); //$NON-NLS-1$
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor progressMonitor2) throws CoreException {
+ IJavaScriptProject[] projects = null;
+ try {
+ projects = model.getJavaScriptProjects();
+ } catch (JavaScriptModelException e) {
+ // could not get JavaScript projects: ignore
+ }
+ if (projects != null) {
+ for (int i = 0, length = projects.length; i < length; i++) {
+ IJavaScriptProject project = projects[i];
+ try {
+ if (JavaBuilder.DEBUG)
+ System.out.println("Touching " + project.getElementName()); //$NON-NLS-1$
+ project.getProject().touch(progressMonitor2);
+ } catch (CoreException e) {
+ // could not touch this project: ignore
+ }
+ }
+ }
+ }
+ };
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_building_after_upgrade);
+ try {
+ ResourcesPlugin.getWorkspace().run(runnable, monitor);
+ } catch (CoreException e) {
+ // could not touch all projects
+ }
+ try {
+ root.setPersistentProperty(qName, newVersionNumber);
+ } catch (CoreException e) {
+ Util.log(e, "Could not persist build state version number"); //$NON-NLS-1$
+ }
+ }
+
+ // ensure external jars are refreshed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93668)
+ try {
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_refreshing_external_jars);
+ model.refreshExternalArchives(
+ null/*refresh all projects*/,
+ monitor == null ? null : new SubProgressMonitor(monitor, 1) // 1% of the time is spent in jar refresh
+ );
+ } catch (JavaScriptModelException e) {
+ // refreshing failed: ignore
+ }
+
+ } finally {
+ if (monitor != null) monitor.done();
+ }
+ }
+ /**
+ * Returns whether a given includepath variable is read-only or not.
+ *
+ * @param variableName
+ * @return true
if the includepath variable is read-only,
+ * false
otherwise.
+ */
+ public static boolean isIncludepathVariableReadOnly(String variableName) {
+ return JavaModelManager.getJavaModelManager().readOnlyVariables.contains(variableName);
+ }
+
+ /**
+ * Returns whether the given file name's extension is a JavaScript-like extension.
+ *
+ * @return whether the given file name's extension is a JavaScript-like extension
+ * @see #getJavaScriptLikeExtensions()
+ */
+ public static boolean isJavaScriptLikeFileName(String fileName) {
+ if(fileName==null) return false;
+ return Util.isJavaLikeFileName(fileName);
+ }
+
+ /**
+ * Returns whether the given marker references the given JavaScript element.
+ * Used for markers, which denote a JavaScript element rather than a resource.
+ *
+ * @param element the element
+ * @param marker the marker
+ * @return true
if the marker references the element, false otherwise
+ * @exception CoreException if the IMarker.getAttribute
on the marker fails
+ */
+ public static boolean isReferencedBy(IJavaScriptElement element, IMarker marker) throws CoreException {
+
+ // only match units or classfiles
+ if (element instanceof IMember){
+ IMember member = (IMember) element;
+ if (member.isBinary()){
+ element = member.getClassFile();
+ } else {
+ element = member.getJavaScriptUnit();
+ }
+ }
+ if (element == null) return false;
+ if (marker == null) return false;
+
+ String markerHandleId = (String)marker.getAttribute(ATT_HANDLE_ID);
+ if (markerHandleId == null) return false;
+
+ IJavaScriptElement markerElement = JavaScriptCore.create(markerHandleId);
+ while (true){
+ if (element.equals(markerElement)) return true; // external elements may still be equal with different handleIDs.
+
+ // cycle through enclosing types in case marker is associated with a classfile (15568)
+ if (markerElement instanceof IClassFile){
+ IType enclosingType = ((IClassFile)markerElement).getType().getDeclaringType();
+ if (enclosingType != null){
+ markerElement = enclosingType.getClassFile(); // retry with immediate enclosing classfile
+ continue;
+ }
+ }
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether the given marker delta references the given JavaScript element.
+ * Used for markers deltas, which denote a JavaScript element rather than a resource.
+ *
+ * @param element the element
+ * @param markerDelta the marker delta
+ * @return true
if the marker delta references the element
+ * @exception CoreException if the IMarkerDelta.getAttribute
on the marker delta fails
+ */
+ public static boolean isReferencedBy(IJavaScriptElement element, IMarkerDelta markerDelta) throws CoreException {
+
+ // only match units or classfiles
+ if (element instanceof IMember){
+ IMember member = (IMember) element;
+ if (member.isBinary()){
+ element = member.getClassFile();
+ } else {
+ element = member.getJavaScriptUnit();
+ }
+ }
+ if (element == null) return false;
+ if (markerDelta == null) return false;
+
+ String markerDeltarHandleId = (String)markerDelta.getAttribute(ATT_HANDLE_ID);
+ if (markerDeltarHandleId == null) return false;
+
+ IJavaScriptElement markerElement = JavaScriptCore.create(markerDeltarHandleId);
+ while (true){
+ if (element.equals(markerElement)) return true; // external elements may still be equal with different handleIDs.
+
+ // cycle through enclosing types in case marker is associated with a classfile (15568)
+ if (markerElement instanceof IClassFile){
+ IType enclosingType = ((IClassFile)markerElement).getType().getDeclaringType();
+ if (enclosingType != null){
+ markerElement = enclosingType.getClassFile(); // retry with immediate enclosing classfile
+ continue;
+ }
+ }
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * Creates and returns a new access rule with the given file pattern and kind.
+ * IAccessRule.K_NON_ACCESSIBLE | IAccessRule.IGNORE_IF_BETTER
.
+ * CPE_CONTAINER
+ * for the given path. This method is fully equivalent to calling
+ * {@link #newContainerEntry(IPath, IAccessRule[], IIncludePathAttribute[], boolean)
+ * newContainerEntry(containerPath, new IAccessRule[0], new IIncludePathAttribute[0], false)}.
+ * CPE_CONTAINER
+ * for the given path. This method is fully equivalent to calling
+ * {@link #newContainerEntry(IPath, IAccessRule[], IIncludePathAttribute[], boolean)
+ * newContainerEntry(containerPath, new IAccessRule[0], new IIncludePathAttribute[0], isExported)}.
+ *
+ * @param containerPath the path identifying the container, it must be formed of at least
+ * one segment (ID+hints)
+ * @param isExported a boolean indicating whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new container includepath entry
+ *
+ * @see JavaScriptCore#getJsGlobalScopeContainer(IPath, IJavaScriptProject)
+ * @see JavaScriptCore#setJsGlobalScopeContainer(IPath, IJavaScriptProject[], IJsGlobalScopeContainer[], IProgressMonitor)
+ */
+ public static IIncludePathEntry newContainerEntry(IPath containerPath, boolean isExported) {
+ return newContainerEntry(
+ containerPath,
+ ClasspathEntry.NO_ACCESS_RULES,
+ ClasspathEntry.NO_EXTRA_ATTRIBUTES,
+ isExported);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_CONTAINER
+ * for the given path. The path of the container will be used during resolution so as to map this
+ * container entry to a set of other includepath entries the container is acting for.
+ * JavaScriptCore.getResolvedJsGlobalScopeContainer
,
+ * and updated with JavaScriptCore.JsGlobalScopeContainerChanged
+ * JsGlobalScopeContainerInitializer
registered onto the
+ * extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer".
+ *
+ *
+ *
+ * containerEntry = JavaScriptCore.newContainerEntry(new Path("MyProvidedJDK/default"));
+ *
+ * <extension
+ * point="org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer">
+ * <containerInitializer
+ * id="MyProvidedJDK"
+ * class="com.example.MyInitializer"/>
+ *
+ * extraAttributes
list contains name/value pairs that must be persisted with
+ * this entry. If no extra attributes are provided, an empty array must be passed in.
+ * Note that this list should not contain any duplicate name.
+ * isExported
flag indicates whether this entry is contributed to dependent
+ * projects. If not exported, dependent projects will not see any of the classes from this entry.
+ * If exported, dependent projects will concatenate the accessible files patterns of this entry with the
+ * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
+ * with the non accessible files patterns of the project.
+ * null
if the primary working copy owner should be used
+ * @exception JavaScriptModelException if an element in the region does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ * @exception IllegalArgumentException if region is null
+ * @return a type hierarchy for all types in the given
+ * region, considering subtypes within that region
+ */
+ public static ITypeHierarchy newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaScriptModelException {
+ if (region == null) {
+ throw new IllegalArgumentException(Messages.hierarchy_nullRegion);
+ }
+ IJavaScriptUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
+ CreateTypeHierarchyOperation op =
+ new CreateTypeHierarchyOperation(region, workingCopies, null, true/*compute subtypes*/);
+ op.runOperation(monitor);
+ return op.getResult();
+ }
+
+ /**
+ * Creates and returns a new non-exported includepath entry of kind CPE_LIBRARY
for the
+ * JAR or folder identified by the given absolute path. This specifies that all package fragments
+ * within the root will have children of type IClassFile
.
+ * This method is fully equivalent to calling
+ * {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IIncludePathAttribute[], boolean)
+ * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IIncludePathAttribute[0], false)}.
+ *
+ * @param path the absolute path of the binary archive
+ * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
+ * or null
if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+ * and will be automatically converted to null
.
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
+ * or null
if this location should be automatically detected.
+ * @return a new library includepath entry
+ */
+ public static IIncludePathEntry newLibraryEntry(
+ IPath path,
+ IPath sourceAttachmentPath,
+ IPath sourceAttachmentRootPath) {
+
+ return newLibraryEntry(
+ path,
+ sourceAttachmentPath,
+ sourceAttachmentRootPath,
+ ClasspathEntry.NO_ACCESS_RULES,
+ ClasspathEntry.NO_EXTRA_ATTRIBUTES,
+ false/*not exported*/);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_LIBRARY
for the JAR or folder
+ * identified by the given absolute path. This specifies that all package fragments within the root
+ * will have children of type IClassFile
.
+ * This method is fully equivalent to calling
+ * {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IIncludePathAttribute[], boolean)
+ * newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IIncludePathAttribute[0], isExported)}.
+ *
+ * @param path the absolute path of the binary archive
+ * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
+ * or null
if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+ * and will be automatically converted to null
.
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
+ * or null
if this location should be automatically detected.
+ * @param isExported indicates whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new library includepath entry
+ */
+ public static IIncludePathEntry newLibraryEntry(
+ IPath path,
+ IPath sourceAttachmentPath,
+ IPath sourceAttachmentRootPath,
+ boolean isExported) {
+
+ return newLibraryEntry(
+ path,
+ sourceAttachmentPath,
+ sourceAttachmentRootPath,
+ ClasspathEntry.NO_ACCESS_RULES,
+ ClasspathEntry.NO_EXTRA_ATTRIBUTES,
+ isExported);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_LIBRARY
for the JAR or folder
+ * identified by the given absolute path. This specifies that all package fragments within the root
+ * will have children of type IClassFile
.
+ * extraAttributes
list contains name/value pairs that must be persisted with
+ * this entry. If no extra attributes are provided, an empty array must be passed in.
+ * Note that this list should not contain any duplicate name.
+ * isExported
flag indicates whether this entry is contributed to dependent
+ * projects. If not exported, dependent projects will not see any of the classes from this entry.
+ * If exported, dependent projects will concatenate the accessible files patterns of this entry with the
+ * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
+ * with the non accessible files patterns of the project.
+ * null
if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+ * and will be automatically converted to null
.
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
+ * or null
if this location should be automatically detected.
+ * @param accessRules the possibly empty list of access rules for this entry
+ * @param extraAttributes the possibly empty list of extra attributes to persist with this entry
+ * @param isExported indicates whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new library includepath entry
+ */
+ public static IIncludePathEntry newLibraryEntry(
+ IPath path,
+ IPath sourceAttachmentPath,
+ IPath sourceAttachmentRootPath,
+ IAccessRule[] accessRules,
+ IIncludePathAttribute[] extraAttributes,
+ boolean isExported) {
+
+ if (path == null) Assert.isTrue(false, "Library path cannot be null"); //$NON-NLS-1$
+ if (!path.isAbsolute()) Assert.isTrue(false, "Path for IIncludePathEntry must be absolute"); //$NON-NLS-1$
+ if (sourceAttachmentPath != null) {
+ if (sourceAttachmentPath.isEmpty()) {
+ sourceAttachmentPath = null; // treat empty path as none
+ } else if (!sourceAttachmentPath.isAbsolute()) {
+ Assert.isTrue(false, "Source attachment path '" //$NON-NLS-1$
+ + sourceAttachmentPath
+ + "' for IIncludePathEntry must be absolute"); //$NON-NLS-1$
+ }
+ }
+ return new ClasspathEntry(
+ IPackageFragmentRoot.K_BINARY,
+ IIncludePathEntry.CPE_LIBRARY,
+ JavaProject.canonicalizedPath(path),
+ ClasspathEntry.INCLUDE_ALL, // inclusion patterns
+ ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
+ sourceAttachmentPath,
+ sourceAttachmentRootPath,
+ null, // specific output folder
+ isExported,
+ accessRules,
+ false, // no access rules to combine
+ extraAttributes);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_LIBRARY
for the JAR or folder
+ * identified by the given absolute path. This specifies that all package fragments within the root
+ * will have children of type IClassFile
.
+ * extraAttributes
list contains name/value pairs that must be persisted with
+ * this entry. If no extra attributes are provided, an empty array must be passed in.
+ * Note that this list should not contain any duplicate name.
+ * isExported
flag indicates whether this entry is contributed to dependent
+ * projects. If not exported, dependent projects will not see any of the classes from this entry.
+ * If exported, dependent projects will concatenate the accessible files patterns of this entry with the
+ * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
+ * with the non accessible files patterns of the project.
+ * null
if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+ * and will be automatically converted to null
.
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
+ * or null
if this location should be automatically detected.
+ * @param accessRules the possibly empty list of access rules for this entry
+ * @param exclusionPatterns the possibly empty list of exclusion patterns
+ * represented as relative paths
+ * @param extraAttributes the possibly empty list of extra attributes to persist with this entry
+ * @param isExported indicates whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new library includepath entry
+ */
+ public static IIncludePathEntry newLibraryEntry(
+ IPath path,
+ IPath sourceAttachmentPath,
+ IPath sourceAttachmentRootPath,
+ IAccessRule[] accessRules,
+ IIncludePathAttribute[] extraAttributes,
+ IPath[] exclusionPatterns,
+ boolean isExported) {
+
+ if (path == null) Assert.isTrue(false, "Library path cannot be null"); //$NON-NLS-1$
+ if (!path.isAbsolute()) Assert.isTrue(false, "Path for IIncludePathEntry must be absolute"); //$NON-NLS-1$
+ if (sourceAttachmentPath != null) {
+ if (sourceAttachmentPath.isEmpty()) {
+ sourceAttachmentPath = null; // treat empty path as none
+ } else if (!sourceAttachmentPath.isAbsolute()) {
+ Assert.isTrue(false, "Source attachment path '" //$NON-NLS-1$
+ + sourceAttachmentPath
+ + "' for IIncludePathEntry must be absolute"); //$NON-NLS-1$
+ }
+ }
+ return new ClasspathEntry(
+ IPackageFragmentRoot.K_BINARY,
+ IIncludePathEntry.CPE_LIBRARY,
+ JavaProject.canonicalizedPath(path),
+ ClasspathEntry.INCLUDE_ALL, // inclusion patterns
+ exclusionPatterns, // exclusion patterns
+ sourceAttachmentPath,
+ sourceAttachmentRootPath,
+ null, // specific output folder
+ isExported,
+ accessRules,
+ false, // no access rules to combine
+ extraAttributes);
+ }
+
+ /**
+ * Creates and returns a new non-exported includepath entry of kind CPE_PROJECT
+ * for the project identified by the given absolute path.
+ * This method is fully equivalent to calling
+ * {@link #newProjectEntry(IPath, IAccessRule[], boolean, IIncludePathAttribute[], boolean)
+ * newProjectEntry(path, new IAccessRule[0], true, new IIncludePathAttribute[0], false)}.
+ *
+ * @param path the absolute path of the binary archive
+ * @return a new project includepath entry
+ */
+ public static IIncludePathEntry newProjectEntry(IPath path) {
+ return newProjectEntry(path, false);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_PROJECT
+ * for the project identified by the given absolute path.
+ * This method is fully equivalent to calling
+ * {@link #newProjectEntry(IPath, IAccessRule[], boolean, IIncludePathAttribute[], boolean)
+ * newProjectEntry(path, new IAccessRule[0], true, new IIncludePathAttribute[0], isExported)}.
+ *
+ * @param path the absolute path of the prerequisite project
+ * @param isExported indicates whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new project includepath entry
+ */
+ public static IIncludePathEntry newProjectEntry(IPath path, boolean isExported) {
+
+ if (!path.isAbsolute()) Assert.isTrue(false, "Path for IIncludePathEntry must be absolute"); //$NON-NLS-1$
+
+ return newProjectEntry(
+ path,
+ ClasspathEntry.NO_ACCESS_RULES,
+ true,
+ ClasspathEntry.NO_EXTRA_ATTRIBUTES,
+ isExported);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_PROJECT
+ * for the project identified by the given absolute path.
+ * combineAccessRules
flag indicates whether access rules of one (or more)
+ * exported entry of the project should be combined with the given access rules. If they should
+ * be combined, the given access rules are considered first, then the entry's access rules are
+ * considered.
+ * extraAttributes
list contains name/value pairs that must be persisted with
+ * this entry. If no extra attributes are provided, an empty array must be passed in.
+ * Note that this list should not contain any duplicate name.
+ * isExported
flag indicates whether this entry is contributed to dependent
+ * projects. If not exported, dependent projects will not see any of the classes from this entry.
+ * If exported, dependent projects will concatenate the accessible files patterns of this entry with the
+ * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
+ * with the non accessible files patterns of the project.
+ * CPE_SOURCE
+ * for all files in the project's source folder identified by the given
+ * absolute workspace-relative path.
+ *
+ * newSourceEntry(path, new IPath[] {}, new IPath[] {}, null);
+ *
+ *
CPE_SOURCE
+ * for the project's source folder identified by the given absolute
+ * workspace-relative path but excluding all source files with paths
+ * matching any of the given patterns.
+ * + * The convenience method is fully equivalent to: + *
+ * newSourceEntry(path, new IPath[] {}, exclusionPatterns, null); + *+ * + * + * @param path the absolute workspace-relative path of a source folder + * @param exclusionPatterns the possibly empty list of exclusion patterns + * represented as relative paths + * @return a new source includepath entry + * @see #newSourceEntry(IPath, IPath[], IPath[], IPath) + */ + public static IIncludePathEntry newSourceEntry(IPath path, IPath[] exclusionPatterns) { + + return newSourceEntry(path, ClasspathEntry.INCLUDE_ALL, exclusionPatterns, null /*output location*/); + } + + /** + * Creates and returns a new includepath entry of kind
CPE_SOURCE
+ * for the project's source folder identified by the given absolute
+ * workspace-relative path but excluding all source files with paths
+ * matching any of the given patterns, and associated with a specific output location
+ * (that is, ".class" files are not going to the project default output location).
+ * + * The convenience method is fully equivalent to: + *
+ * newSourceEntry(path, new IPath[] {}, exclusionPatterns, specificOutputLocation); + *+ * + * + * @param path the absolute workspace-relative path of a source folder + * @param exclusionPatterns the possibly empty list of exclusion patterns + * represented as relative paths + * @param specificOutputLocation the specific output location for this source entry (
null
if using project default ouput location)
+ * @return a new source includepath entry
+ * @see #newSourceEntry(IPath, IPath[], IPath[], IPath)
+ */
+ public static IIncludePathEntry newSourceEntry(IPath path, IPath[] exclusionPatterns, IPath specificOutputLocation) {
+
+ return newSourceEntry(path, ClasspathEntry.INCLUDE_ALL, exclusionPatterns, specificOutputLocation);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_SOURCE
+ * for the project's source folder identified by the given absolute
+ * workspace-relative path but excluding all source files with paths
+ * matching any of the given patterns, and associated with a specific output location
+ * (that is, ".class" files are not going to the project default output location).
+ * + * The convenience method is fully equivalent to: + *
+ * newSourceEntry(path, new IPath[] {}, exclusionPatterns, specificOutputLocation, new IIncludePathAttribute[] {}); + *+ * + * + * @param path the absolute workspace-relative path of a source folder + * @param inclusionPatterns the possibly empty list of inclusion patterns + * represented as relative paths + * @param exclusionPatterns the possibly empty list of exclusion patterns + * represented as relative paths + * @param specificOutputLocation the specific output location for this source entry (
null
if using project default ouput location)
+ * @return a new source includepath entry
+ * @see #newSourceEntry(IPath, IPath[], IPath[], IPath, IIncludePathAttribute[])
+ */
+ public static IIncludePathEntry newSourceEntry(IPath path, IPath[] inclusionPatterns, IPath[] exclusionPatterns, IPath specificOutputLocation) {
+ return newSourceEntry(path, inclusionPatterns, exclusionPatterns, specificOutputLocation, ClasspathEntry.NO_EXTRA_ATTRIBUTES);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_SOURCE
+ * for the project's source folder identified by the given absolute
+ * workspace-relative path using the given inclusion and exclusion patterns
+ * to determine which source files are included, and the given output path
+ * to control the output location of generated files.
+ *
+ * The source folder is referred to using an absolute path relative to the
+ * workspace root, e.g. /Project/src
. A project's source
+ * folders are located with that project. That is, a source includepath
+ * entry specifying the path /P1/src
is only usable for
+ * project P1
.
+ *
+ * The inclusion patterns determines the initial set of source files that
+ * are to be included; the exclusion patterns are then used to reduce this
+ * set. When no inclusion patterns are specified, the initial file set
+ * includes all relevent files in the resource tree rooted at the source
+ * entry's path. On the other hand, specifying one or more inclusion
+ * patterns means that all and only files matching at least one of
+ * the specified patterns are to be included. If exclusion patterns are
+ * specified, the initial set of files is then reduced by eliminating files
+ * matched by at least one of the exclusion patterns. Inclusion and
+ * exclusion patterns look like relative file paths with wildcards and are
+ * interpreted relative to the source entry's path. File patterns are
+ * case-sensitive can contain '**', '*' or '?' wildcards (see
+ * {@link IIncludePathEntry#getExclusionPatterns()} for the full description
+ * of their syntax and semantics). The resulting set of files are included
+ * in the corresponding package fragment root; all package fragments within
+ * the root will have children of type IJavaScriptUnit
.
+ *
+ * Also note that all sources/binaries inside a project are contributed as
+ * a whole through a project entry
+ * (see JavaScriptCore.newProjectEntry
). Particular source entries
+ * cannot be selectively exported.
+ *
+ * The extraAttributes
list contains name/value pairs that must be persisted with
+ * this entry. If no extra attributes are provided, an empty array must be passed in.
+ * Note that this list should not contain any duplicate name.
+ *
null
if using project default ouput location)
+ * @param extraAttributes the possibly empty list of extra attributes to persist with this entry
+ * @return a new source includepath entry with the given exclusion patterns
+ * @see IIncludePathEntry#getInclusionPatterns()
+ * @see IIncludePathEntry#getExclusionPatterns()
+ * @see IIncludePathEntry#getOutputLocation()
+ */
+ public static IIncludePathEntry newSourceEntry(IPath path, IPath[] inclusionPatterns, IPath[] exclusionPatterns, IPath specificOutputLocation, IIncludePathAttribute[] extraAttributes) {
+
+ if (path == null) Assert.isTrue(false, "Source path cannot be null"); //$NON-NLS-1$
+ if (!path.isAbsolute()) Assert.isTrue(false, "Path for IIncludePathEntry must be absolute"); //$NON-NLS-1$
+ if (exclusionPatterns == null) Assert.isTrue(false, "Exclusion pattern set cannot be null"); //$NON-NLS-1$
+ if (inclusionPatterns == null) Assert.isTrue(false, "Inclusion pattern set cannot be null"); //$NON-NLS-1$
+
+ return new ClasspathEntry(
+ IPackageFragmentRoot.K_SOURCE,
+ IIncludePathEntry.CPE_SOURCE,
+ path,
+ inclusionPatterns,
+ exclusionPatterns,
+ null, // source attachment
+ null, // source attachment root
+ specificOutputLocation, // custom output location
+ false,
+ null,
+ false, // no access rules to combine
+ extraAttributes);
+ }
+
+ /**
+ * Creates and returns a new non-exported includepath entry of kind CPE_VARIABLE
+ * for the given path. This method is fully equivalent to calling
+ * {@link #newVariableEntry(IPath, IPath, IPath, IAccessRule[], IIncludePathAttribute[], boolean)
+ * newVariableEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IIncludePathAttribute[0], false)}.
+ *
+ * @param variablePath the path of the binary archive; first segment is the
+ * name of a includepath variable
+ * @param variableSourceAttachmentPath the path of the corresponding source archive,
+ * or null
if none; if present, the first segment is the
+ * name of a includepath variable (not necessarily the same variable
+ * as the one that begins variablePath
)
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive
+ * or null
if variableSourceAttachmentPath
is also null
+ * @return a new library includepath entry
+ */
+ public static IIncludePathEntry newVariableEntry(
+ IPath variablePath,
+ IPath variableSourceAttachmentPath,
+ IPath sourceAttachmentRootPath) {
+
+ return newVariableEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, false);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_VARIABLE
+ * for the given path. This method is fully equivalent to calling
+ * {@link #newVariableEntry(IPath, IPath, IPath, IAccessRule[], IIncludePathAttribute[], boolean)
+ * newVariableEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IIncludePathAttribute[0], isExported)}.
+ *
+ * @param variablePath the path of the binary archive; first segment is the
+ * name of a includepath variable
+ * @param variableSourceAttachmentPath the path of the corresponding source archive,
+ * or null
if none; if present, the first segment is the
+ * name of a includepath variable (not necessarily the same variable
+ * as the one that begins variablePath
)
+ * @param variableSourceAttachmentRootPath the location of the root of the source files within the source archive
+ * or null
if variableSourceAttachmentPath
is also null
+ * @param isExported indicates whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new variable includepath entry
+ */
+ public static IIncludePathEntry newVariableEntry(
+ IPath variablePath,
+ IPath variableSourceAttachmentPath,
+ IPath variableSourceAttachmentRootPath,
+ boolean isExported) {
+
+ return newVariableEntry(
+ variablePath,
+ variableSourceAttachmentPath,
+ variableSourceAttachmentRootPath,
+ ClasspathEntry.NO_ACCESS_RULES,
+ ClasspathEntry.NO_EXTRA_ATTRIBUTES,
+ isExported);
+ }
+
+ /**
+ * Creates and returns a new includepath entry of kind CPE_VARIABLE
+ * for the given path. The first segment of the path is the name of a includepath variable.
+ * The trailing segments of the path will be appended to resolved variable path.
+ * + * A variable entry allows to express indirect references on a includepath to other projects or libraries, + * depending on what the includepath variable is referring. + *
+ * It is possible to register an automatic initializer (JsGlobalScopeVariableInitializer
),
+ * which will be invoked through the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeVariableInitializer".
+ * After resolution, a includepath variable entry may either correspond to a project or a library entry.
+ *
+ * The extraAttributes
list contains name/value pairs that must be persisted with
+ * this entry. If no extra attributes are provided, an empty array must be passed in.
+ * Note that this list should not contain any duplicate name.
+ *
+ * The isExported
flag indicates whether this entry is contributed to dependent
+ * projects. If not exported, dependent projects will not see any of the classes from this entry.
+ * If exported, dependent projects will concatenate the accessible files patterns of this entry with the
+ * accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
+ * with the non accessible files patterns of the project.
+ *
+ * Note that this operation does not attempt to validate includepath variables + * or access the resources at the given paths. + *
+ * + * @param variablePath the path of the binary archive; first segment is the + * name of a includepath variable + * @param variableSourceAttachmentPath the path of the corresponding source archive, + * ornull
if none; if present, the first segment is the
+ * name of a includepath variable (not necessarily the same variable
+ * as the one that begins variablePath
)
+ * @param variableSourceAttachmentRootPath the location of the root of the source files within the source archive
+ * or null
if variableSourceAttachmentPath
is also null
+ * @param accessRules the possibly empty list of access rules for this entry
+ * @param extraAttributes the possibly empty list of extra attributes to persist with this entry
+ * @param isExported indicates whether this entry is contributed to dependent
+ * projects in addition to the output location
+ * @return a new variable includepath entry
+ */
+ public static IIncludePathEntry newVariableEntry(
+ IPath variablePath,
+ IPath variableSourceAttachmentPath,
+ IPath variableSourceAttachmentRootPath,
+ IAccessRule[] accessRules,
+ IIncludePathAttribute[] extraAttributes,
+ boolean isExported) {
+
+ if (variablePath == null) Assert.isTrue(false, "Variable path cannot be null"); //$NON-NLS-1$
+ if (variablePath.segmentCount() < 1) {
+ Assert.isTrue(
+ false,
+ "Illegal includepath variable path: \'" + variablePath.makeRelative().toString() + "\', must have at least one segment"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ return new ClasspathEntry(
+ IPackageFragmentRoot.K_SOURCE,
+ IIncludePathEntry.CPE_VARIABLE,
+ variablePath,
+ ClasspathEntry.INCLUDE_ALL, // inclusion patterns
+ ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
+ variableSourceAttachmentPath, // source attachment
+ variableSourceAttachmentRootPath, // source attachment root
+ null, // specific output folder
+ isExported,
+ accessRules,
+ false, // no access rules to combine
+ extraAttributes);
+ }
+
+ /**
+ * Removed the given includepath variable. Does nothing if no value was
+ * set for this includepath variable.
+ * + * This functionality cannot be used while the resource tree is locked. + *
+ * Includepath variable values are persisted locally to the workspace, and + * are preserved from session to session. + *
+ * + * @param variableName the name of the includepath variable + * @param monitor the progress monitor to report progress + * @see #setIncludepathVariable(String, IPath) + */ + public static void removeIncludepathVariable(String variableName, IProgressMonitor monitor) { + try { + SetVariablesOperation operation = new SetVariablesOperation(new String[]{ variableName}, new IPath[]{ null }, true/*update preferences*/); + operation.runOperation(monitor); + } catch (JavaScriptModelException e) { + Util.log(e, "Exception while removing variable " + variableName); //$NON-NLS-1$ + } + } + + /** + * Removes the given element changed listener. + * Has no affect if an identical listener is not registered. + * + * @param listener the listener + */ + public static void removeElementChangedListener(IElementChangedListener listener) { + JavaModelManager.getJavaModelManager().deltaState.removeElementChangedListener(listener); + } + + /** + * Removes the file extension from the given file name, if it has a JavaScript-like file + * extension. Otherwise the file name itself is returned. + * Note this removes the dot ('.') before the extension as well. + * + * @param fileName the name of a file + * @return the fileName without the JavaScript-like extension + */ + public static String removeJavaScriptLikeExtension(String fileName) { + return Util.getNameWithoutJavaLikeExtension(fileName); + } + + /** + * Removes the given pre-processing resource changed listener. + *
+ * Has no affect if an identical listener is not registered. + * + * @param listener the listener + */ + public static void removePreProcessingResourceChangedListener(IResourceChangeListener listener) { + JavaModelManager.getJavaModelManager().deltaState.removePreResourceChangedListener(listener); + } + + + + /** + * Runs the given action as an atomic JavaScript model operation. + *
+ * After running a method that modifies javaScript elements, + * registered listeners receive after-the-fact notification of + * what just transpired, in the form of a element changed event. + * This method allows clients to call a number of + * methods that modify javaScript elements and only have element + * changed event notifications reported at the end of the entire + * batch. + *
+ *+ * If this method is called outside the dynamic scope of another such + * call, this method runs the action and then reports a single + * element changed event describing the net effect of all changes + * done to javaScript elements by the action. + *
+ *+ * If this method is called in the dynamic scope of another such + * call, this method simply runs the action. + *
+ * + * @param action the action to perform + * @param monitor a progress monitor, ornull
if progress
+ * reporting and cancellation are not desired
+ * @exception CoreException if the operation failed.
+ */
+ public static void run(IWorkspaceRunnable action, IProgressMonitor monitor) throws CoreException {
+ run(action, ResourcesPlugin.getWorkspace().getRoot(), monitor);
+ }
+ /**
+ * Runs the given action as an atomic JavaScript model operation.
+ * + * After running a method that modifies javaScript elements, + * registered listeners receive after-the-fact notification of + * what just transpired, in the form of a element changed event. + * This method allows clients to call a number of + * methods that modify javaScript elements and only have element + * changed event notifications reported at the end of the entire + * batch. + *
+ *+ * If this method is called outside the dynamic scope of another such + * call, this method runs the action and then reports a single + * element changed event describing the net effect of all changes + * done to javaScript elements by the action. + *
+ *+ * If this method is called in the dynamic scope of another such + * call, this method simply runs the action. + *
+ *
+ * The supplied scheduling rule is used to determine whether this operation can be
+ * run simultaneously with workspace changes in other threads. See
+ * IWorkspace.run(...)
for more details.
+ *
null
if there are no scheduling restrictions for this operation.
+ * @param monitor a progress monitor, or null
if progress
+ * reporting and cancellation are not desired
+ * @exception CoreException if the operation failed.
+ */
+ public static void run(IWorkspaceRunnable action, ISchedulingRule rule, IProgressMonitor monitor) throws CoreException {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ if (workspace.isTreeLocked()) {
+ new BatchOperation(action).run(monitor);
+ } else {
+ // use IWorkspace.run(...) to ensure that a build will be done in autobuild mode
+ workspace.run(new BatchOperation(action), rule, IWorkspace.AVOID_UPDATE, monitor);
+ }
+ }
+ /**
+ * Bind a container reference path to some actual containers (IJsGlobalScopeContainer
).
+ * This API must be invoked whenever changes in container need to be reflected onto the JavaModel.
+ * Containers can have distinct values in different projects, therefore this API considers a
+ * set of projects with their respective containers.
+ *
+ * containerPath
is the path under which these values can be referenced through
+ * container includepath entries (IIncludePathEntry#CPE_CONTAINER
). A container path
+ * is formed by a first ID segment followed with extra segments, which can be used as additional hints
+ * for the resolution. The container ID is used to identify a JsGlobalScopeContainerInitializer
+ * registered on the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer".
+ *
+ * There is no assumption that each individual container value passed in argument
+ * (respectiveContainers
) must answer the exact same path when requested
+ * IJsGlobalScopeContainer#getPath
.
+ * Indeed, the containerPath is just an indication for resolving it to an actual container object. It can be
+ * delegated to a JsGlobalScopeContainerInitializer
, which can be activated through the extension
+ * point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer").
+ *
+ * In reaction to changing container values, the JavaModel will be updated to reflect the new + * state of the updated container. A combined JavaScript element delta will be notified to describe the corresponding + * includepath changes resulting from the container update. This operation is batched, and automatically eliminates + * unnecessary updates (new container is same as old one). This operation acquires a lock on the workspace's root. + *
+ * This functionality cannot be used while the workspace is locked, since + * it may create/remove some resource markers. + *
+ * Includepath container values are persisted locally to the workspace, but
+ * are not preserved from a session to another. It is thus highly recommended to register a
+ * JsGlobalScopeContainerInitializer
for each referenced container
+ * (through the extension point "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer").
+ *
+ * Note: setting a container to null
will cause it to be lazily resolved again whenever
+ * its value is required. In particular, this will cause a registered initializer to be invoked
+ * again.
+ *
+ * @param containerPath - the name of the container reference, which is being updated + * @param affectedProjects - the set of projects for which this container is being bound + * @param respectiveContainers - the set of respective containers for the affected projects + * @param monitor a monitor to report progress + * @throws JavaScriptModelException + * @see JsGlobalScopeContainerInitializer + * @see #getJsGlobalScopeContainer(IPath, IJavaScriptProject) + * @see IJsGlobalScopeContainer + */ + public static void setJsGlobalScopeContainer(IPath containerPath, IJavaScriptProject[] affectedProjects, IJsGlobalScopeContainer[] respectiveContainers, IProgressMonitor monitor) throws JavaScriptModelException { + if (affectedProjects.length != respectiveContainers.length) + Assert.isTrue(false, "Projects and containers collections should have the same size"); //$NON-NLS-1$ + SetContainerOperation operation = new SetContainerOperation(containerPath, affectedProjects, respectiveContainers); +// operation.runOperation(monitor); + + operation.progressMonitor=monitor; + + operation.execute(); + + + + } + + /** + * Sets the value of the given includepath variable. + * The path must have at least one segment. + *
+ * This functionality cannot be used while the resource tree is locked. + *
+ * Includepath variable values are persisted locally to the workspace, and + * are preserved from session to session. + *
+ * + * @param variableName the name of the includepath variable + * @param path the path + * @throws JavaScriptModelException + * @see #getIncludepathVariable(String) + * + * @deprecated Use {@link #setIncludepathVariable(String, IPath, IProgressMonitor)} instead + */ + public static void setIncludepathVariable(String variableName, IPath path) + throws JavaScriptModelException { + + setIncludepathVariable(variableName, path, null); + } + + /** + * Sets the value of the given includepath variable. + * The path must not be null. + *
+ * This functionality cannot be used while the resource tree is locked. + *
+ * Includepath variable values are persisted locally to the workspace, and + * are preserved from session to session. + *
+ * Updating a variable with the same value has no effect. + * + * @param variableName the name of the includepath variable + * @param path the path + * @param monitor a monitor to report progress + * @throws JavaScriptModelException + * @see #getIncludepathVariable(String) + */ + public static void setIncludepathVariable( + String variableName, + IPath path, + IProgressMonitor monitor) + throws JavaScriptModelException { + + if (path == null) Assert.isTrue(false, "Variable path cannot be null"); //$NON-NLS-1$ + setIncludepathVariables(new String[]{variableName}, new IPath[]{ path }, monitor); + } + + /** + * Sets the values of all the given includepath variables at once. + * Null paths can be used to request corresponding variable removal. + *
+ * A combined JavaScript element delta will be notified to describe the corresponding + * includepath changes resulting from the variables update. This operation is batched, + * and automatically eliminates unnecessary updates (new variable is same as old one). + * This operation acquires a lock on the workspace's root. + *
+ * This functionality cannot be used while the workspace is locked, since + * it may create/remove some resource markers. + *
+ * Includepath variable values are persisted locally to the workspace, and + * are preserved from session to session. + *
+ * Updating a variable with the same value has no effect. + * + * @param variableNames an array of names for the updated includepath variables + * @param paths an array of path updates for the modified includepath variables (null + * meaning that the corresponding value will be removed + * @param monitor a monitor to report progress + * @throws JavaScriptModelException + * @see #getIncludepathVariable(String) + */ + public static void setIncludepathVariables( + String[] variableNames, + IPath[] paths, + IProgressMonitor monitor) + throws JavaScriptModelException { + + if (variableNames.length != paths.length) Assert.isTrue(false, "Variable names and paths collections should have the same size"); //$NON-NLS-1$ + SetVariablesOperation operation = new SetVariablesOperation(variableNames, paths, true/*update preferences*/); + operation.runOperation(monitor); + } + + /** + * Sets the default's validator options inside the given options map according + * to the given compliance. + * + *
The given compliance must be one of the compliance supported by the validator. + * See {@link #getDefaultOptions()} for a list of compliance values.
+ * + *The list of modified options is:
+ *If the given compliance is unknown, the given map is unmodified.
+ * + * @param compliance the given compliance + * @param options the given options map + */ + public static void setComplianceOptions(String compliance, Map options) { + switch((int) (CompilerOptions.versionToJdkLevel(compliance) >>> 16)) { + case ClassFileConstants.MAJOR_VERSION_1_3: + options.put(JavaScriptCore.COMPILER_COMPLIANCE, JavaScriptCore.VERSION_1_3); + options.put(JavaScriptCore.COMPILER_SOURCE, JavaScriptCore.VERSION_1_3); + options.put(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_1); + options.put(JavaScriptCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaScriptCore.IGNORE); + break; + case ClassFileConstants.MAJOR_VERSION_1_4: + options.put(JavaScriptCore.COMPILER_COMPLIANCE, JavaScriptCore.VERSION_1_4); + options.put(JavaScriptCore.COMPILER_SOURCE, JavaScriptCore.VERSION_1_3); + options.put(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_2); + options.put(JavaScriptCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaScriptCore.WARNING); + break; + case ClassFileConstants.MAJOR_VERSION_1_5: + options.put(JavaScriptCore.COMPILER_COMPLIANCE, JavaScriptCore.VERSION_1_5); + options.put(JavaScriptCore.COMPILER_SOURCE, JavaScriptCore.VERSION_1_5); + options.put(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_5); + options.put(JavaScriptCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaScriptCore.ERROR); + break; + case ClassFileConstants.MAJOR_VERSION_1_6: + options.put(JavaScriptCore.COMPILER_COMPLIANCE, JavaScriptCore.VERSION_1_6); + options.put(JavaScriptCore.COMPILER_SOURCE, JavaScriptCore.VERSION_1_6); + options.put(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_6); + options.put(JavaScriptCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaScriptCore.ERROR); + break; + case ClassFileConstants.MAJOR_VERSION_1_7: + options.put(JavaScriptCore.COMPILER_COMPLIANCE, JavaScriptCore.VERSION_1_7); + options.put(JavaScriptCore.COMPILER_SOURCE, JavaScriptCore.VERSION_1_7); + options.put(JavaScriptCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaScriptCore.VERSION_1_7); + options.put(JavaScriptCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaScriptCore.ERROR); + } + } + + /** + * Sets the current table of options. All and only the options explicitly + * included in the given table are remembered; all previous option settings + * are forgotten, including ones not explicitly mentioned. + *
+ * For a complete description of the configurable options, see
+ * getDefaultOptions
.
+ *
String
; value type:
+ * String
), or null
to reset all
+ * options to their default values
+ * @see JavaScriptCore#getDefaultOptions()
+ * @see org.eclipse.wst.jsdt.internal.core.JavaCorePreferenceInitializer for changing default settings
+ */
+ public static void setOptions(Hashtable newOptions) {
+ JavaModelManager.getJavaModelManager().setOptions(newOptions);
+ }
+
+ /* (non-Javadoc)
+ * Shutdown the JavaScriptCore plug-in.
+ * + * De-registers the JavaModelManager as a resource changed listener and save participant. + *
+ * @see org.eclipse.core.runtime.Plugin#stop(BundleContext) + */ + public void stop(BundleContext context) throws Exception { + try { + JavaModelManager.getJavaModelManager().shutdown(); + } finally { + // ensure we call super.stop as the last thing + super.stop(context); + } + } + + /* (non-Javadoc) + * Startup the JavaScriptCore plug-in. + *
+ * Registers the JavaModelManager as a resource changed listener and save participant. + * Starts the background indexing, and restore saved includepath variable values. + *
+ * @throws Exception + * @see org.eclipse.core.runtime.Plugin#start(BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + JavaModelManager.getJavaModelManager().startup(); + } + public static String getSystemPath() + { + URL url=FileLocator.find(getJavaScriptCore().getBundle(),new Path("libraries"),null); //$NON-NLS-1$ + return url.getFile(); + } + + + public static boolean isReadOnly(IResource resource) + { + QualifiedName qn=new QualifiedName(JavaScriptCore.PLUGIN_ID,JavaScriptCore.READ_ONLY_SOURCE_PROPERTY); + try { + String persistentProperty = resource.getPersistentProperty(qn); + return "true".equals(persistentProperty); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return false; + } + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JavaScriptModelException.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JavaScriptModelException.java new file mode 100644 index 0000000..daed779 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JavaScriptModelException.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core; + +import java.io.PrintStream; +import java.io.PrintWriter; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.wst.jsdt.internal.core.JavaModelStatus; + +/** + * A checked exception representing a failure in the JavaScript model. + * JavaScript model exceptions contain a JavaScript-specific status object describing the + * cause of the exception. + *
+ * This class is not intended to be subclassed by clients. Instances of this + * class are automatically created by the JavaScript model when problems arise, so + * there is generally no need for clients to create instances. + *
+ * + * @see IJavaScriptModelStatus + * @see IJavaScriptModelStatusConstants + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class JavaScriptModelException extends CoreException { + + private static final long serialVersionUID = -760398656505871287L; // backward compatible + + CoreException nestedCoreException; +/** + * Creates a JavaScript model exception that wrappers the givenThrowable
.
+ * The exception contains a JavaScript-specific status object with severity
+ * IStatus.ERROR
and the given status code.
+ *
+ * @param e the Throwable
+ * @param code one of the JavaScript-specific status codes declared in
+ * IJavaScriptModelStatusConstants
+ * @see IJavaScriptModelStatusConstants
+ * @see org.eclipse.core.runtime.IStatus#ERROR
+ */
+public JavaScriptModelException(Throwable e, int code) {
+ this(new JavaModelStatus(code, e));
+}
+/**
+ * Creates a JavaScript model exception for the given CoreException
.
+ * Equivalent to
+ * JavaScriptModelException(exception,IJavaScriptModelStatusConstants.CORE_EXCEPTION
.
+ *
+ * @param exception the CoreException
+ */
+public JavaScriptModelException(CoreException exception) {
+ super(exception.getStatus());
+ this.nestedCoreException = exception;
+}
+/**
+ * Creates a JavaScript model exception for the given JavaScript-specific status object.
+ *
+ * @param status the JavaScript-specific status object
+ */
+public JavaScriptModelException(IJavaScriptModelStatus status) {
+ super(status);
+}
+/**
+ * Returns the underlying Throwable
that caused the failure.
+ *
+ * @return the wrappered Throwable
, or null
if the
+ * direct case of the failure was at the JavaScript model layer
+ */
+public Throwable getException() {
+ if (this.nestedCoreException == null) {
+ return getStatus().getException();
+ } else {
+ return this.nestedCoreException;
+ }
+}
+/**
+ * Returns the JavaScript model status object for this exception.
+ * Equivalent to (IJavaScriptModelStatus) getStatus()
.
+ *
+ * @return a status object
+ */
+public IJavaScriptModelStatus getJavaScriptModelStatus() {
+ IStatus status = this.getStatus();
+ if (status instanceof IJavaScriptModelStatus) {
+ return (IJavaScriptModelStatus)status;
+ } else {
+ // A regular IStatus is created only in the case of a CoreException.
+ // See bug 13492 Should handle JavaModelExceptions that contains CoreException more gracefully
+ return new JavaModelStatus(this.nestedCoreException);
+ }
+}
+/**
+ * Returns whether this exception indicates that a JavaScript model element does not
+ * exist. Such exceptions have a status with a code of
+ * IJavaScriptModelStatusConstants.ELEMENT_DOES_NOT_EXIST
or
+ * IJavaScriptModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH
.
+ * This is a convenience method.
+ *
+ * @return true
if this exception indicates that a JavaScript model
+ * element does not exist
+ * @see IJavaScriptModelStatus#isDoesNotExist()
+ * @see IJavaScriptModelStatusConstants#ELEMENT_DOES_NOT_EXIST
+ * @see IJavaScriptModelStatusConstants#ELEMENT_NOT_ON_CLASSPATH
+ */
+public boolean isDoesNotExist() {
+ IJavaScriptModelStatus javaModelStatus = getJavaScriptModelStatus();
+ return javaModelStatus != null && javaModelStatus.isDoesNotExist();
+}
+
+/**
+ * Prints this exception's stack trace to the given print stream.
+ *
+ * @param output the print stream
+ */
+public void printStackTrace(PrintStream output) {
+ synchronized(output) {
+ super.printStackTrace(output);
+ Throwable throwable = getException();
+ if (throwable != null) {
+ output.print("Caused by: "); //$NON-NLS-1$
+ throwable.printStackTrace(output);
+ }
+ }
+}
+
+/**
+ * Prints this exception's stack trace to the given print writer.
+ *
+ * @param output the print writer
+ */
+public void printStackTrace(PrintWriter output) {
+ synchronized(output) {
+ super.printStackTrace(output);
+ Throwable throwable = getException();
+ if (throwable != null) {
+ output.print("Caused by: "); //$NON-NLS-1$
+ throwable.printStackTrace(output);
+ }
+ }
+}
+/*
+ * Returns a printable representation of this exception suitable for debugging
+ * purposes only.
+ */
+public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append("JavaScript Model Exception: "); //$NON-NLS-1$
+ if (getException() != null) {
+ if (getException() instanceof CoreException) {
+ CoreException c= (CoreException)getException();
+ buffer.append("Core Exception [code "); //$NON-NLS-1$
+ buffer.append(c.getStatus().getCode());
+ buffer.append("] "); //$NON-NLS-1$
+ buffer.append(c.getStatus().getMessage());
+ } else {
+ buffer.append(getException().toString());
+ }
+ } else {
+ buffer.append(getStatus().toString());
+ }
+ return buffer.toString();
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JsGlobalScopeContainerInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JsGlobalScopeContainerInitializer.java
new file mode 100644
index 0000000..aa265ff
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JsGlobalScopeContainerInitializer.java
@@ -0,0 +1,321 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - added support for requesting updates of a particular
+ * container for generic container operations.
+ * - canUpdateJsGlobalScopeContainer(IPath, IJavaScriptProject)
+ * - requestJsGlobalScopeContainerUpdate(IPath, IJavaScriptProject, IJsGlobalScopeContainer)
+ * IBM Corporation - allow initializers to provide a readable description
+ * of a container reference, ahead of actual resolution.
+ * - getDescription(IPath, IJavaScriptProject)
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.net.URI;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.wst.jsdt.core.compiler.libraries.LibraryLocation;
+import org.eclipse.wst.jsdt.internal.core.JavaModelStatus;
+
+/**
+ * Abstract base implementation of all includepath container initializer.
+ * Includepath variable containers are used in conjunction with the
+ * "org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer" extension point.
+ *
+ * Clients should subclass this class to implement a specific includepath
+ * container initializer. The subclass must have a public 0-argument
+ * constructor and a concrete implementation of initialize
.
+ *
+ * Multiple includepath containers can be registered, each of them declares + * the container ID they can handle, so as to narrow the set of containers they + * can resolve, in other words, a container initializer is guaranteed to only be + * activated to resolve containers which match the ID they registered onto. + *
+ * In case multiple container initializers collide on the same container ID, the first + * registered one will be invoked. + * + * @see IIncludePathEntry + * @see IJsGlobalScopeContainer + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public abstract class JsGlobalScopeContainerInitializer implements IJsGlobalScopeContainerInitializer, IJsGlobalScopeContainer { + + /** + * Status code indicating that an attribute is not supported. + * + * @see #getAccessRulesStatus(IPath, IJavaScriptProject) + * @see #getAttributeStatus(IPath, IJavaScriptProject, String) + * @see #getSourceAttachmentStatus(IPath, IJavaScriptProject) + * + */ + public static final int ATTRIBUTE_NOT_SUPPORTED = 1; + + /** + * Status code indicating that an attribute is not modifiable. + * + * @see #getAccessRulesStatus(IPath, IJavaScriptProject) + * @see #getAttributeStatus(IPath, IJavaScriptProject, String) + * @see #getSourceAttachmentStatus(IPath, IJavaScriptProject) + * + */ + public static final int ATTRIBUTE_READ_ONLY = 2; + + /** + * Creates a new includepath container initializer. + */ + public JsGlobalScopeContainerInitializer() { + // a includepath container initializer must have a public 0-argument constructor + } + + public void initialize(IPath containerPath, IJavaScriptProject project) throws CoreException { + JavaScriptCore.setJsGlobalScopeContainer(containerPath, new IJavaScriptProject[] { project }, new IJsGlobalScopeContainer[] { getContainer(containerPath, project) }, null); + } + + protected IJsGlobalScopeContainer getContainer(IPath containerPath, IJavaScriptProject project) { + return this; + } + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#canUpdateJsGlobalScopeContainer(org.eclipse.core.runtime.IPath, org.eclipse.wst.jsdt.core.IJavaScriptProject) + */ + public boolean canUpdateJsGlobalScopeContainer(IPath containerPath, IJavaScriptProject project) { + if(project==null || containerPath==null) return true; + LibrarySuperType superType = project.getCommonSuperType(); + return superType!=null && superType.getRawContainerPath().equals(getPath()); + } + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#requestJsGlobalScopeContainerUpdate(org.eclipse.core.runtime.IPath, org.eclipse.wst.jsdt.core.IJavaScriptProject, org.eclipse.wst.jsdt.core.IJsGlobalScopeContainer) + */ + public void requestJsGlobalScopeContainerUpdate(IPath containerPath, IJavaScriptProject project, IJsGlobalScopeContainer containerSuggestion) throws CoreException { + + // By default, includepath container initializers do not accept updating containers + } + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#getDescription(org.eclipse.core.runtime.IPath, org.eclipse.wst.jsdt.core.IJavaScriptProject) + */ + public String getDescription(IPath containerPath, IJavaScriptProject project) { + + // By default, a container path is the only available description + return containerPath.makeRelative().toString(); + } + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#getFailureContainer(org.eclipse.core.runtime.IPath, org.eclipse.wst.jsdt.core.IJavaScriptProject) + */ + public IJsGlobalScopeContainer getFailureContainer(final IPath containerPath, IJavaScriptProject project) { + final String description = getDescription(containerPath, project); + return + new IJsGlobalScopeContainer() { + public IIncludePathEntry[] getIncludepathEntries() { + return new IIncludePathEntry[0]; + } + public String getDescription() { + return description; + } + public int getKind() { + return 0; + } + public IPath getPath() { + return containerPath; + } + public String toString() { + return getDescription(); + } + public String[] resolvedLibraryImport(String a) { + return new String[] {a}; + } + }; + } + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#getComparisonID(org.eclipse.core.runtime.IPath, org.eclipse.wst.jsdt.core.IJavaScriptProject) + */ + public Object getComparisonID(IPath containerPath, IJavaScriptProject project) { + + // By default, containers are identical if they have the same containerPath first segment, + // but this may be refined by other container initializer implementations. + if (containerPath == null) { + return null; + } else { + return containerPath.segment(0); + } + } + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#getHostPath(org.eclipse.core.runtime.IPath, org.eclipse.wst.jsdt.core.IJavaScriptProject) + */ + public URI getHostPath(IPath path, IJavaScriptProject project) { + return null; + } + + public boolean allowAttachJsDoc() { return true; } + /* + * returns a String of all SuperTypes provided by this library. + */ + public String[] containerSuperTypes() {return new String[0];} + + /* Return a string of imports to replace the real imports for. necisary for toolkits and other t + * things that may have a certain import best for runtime but not best for building a model + * + */ + public String[] resolvedLibraryImport(String realImport) { + return new String[] {realImport}; + } + + public IIncludePathEntry[] getIncludepathEntries() { + LibraryLocation libLocation = getLibraryLocation(); + char[][] filesInLibs = libLocation.getLibraryFileNames(); + IIncludePathEntry[] entries = new IIncludePathEntry[filesInLibs.length]; + for (int i = 0; i < entries.length; i++) { + IPath workingLibPath = new Path(libLocation.getLibraryPath(filesInLibs[i])); + entries[i] = JavaScriptCore.newLibraryEntry(workingLibPath.makeAbsolute(), null, null, new IAccessRule[0], new IIncludePathAttribute[0], true); + } + return entries; + } + + public String getDescription() { + return null; + } + + public int getKind() { + + return K_APPLICATION; + } + + public IPath getPath() { + + return null; + } + /** + * Returns the access rules attribute status according to this initializer. + *
+ * The returned {@link IStatus status} can have one of the following severities: + *
+ * The status message can contain more information. + *
+ * If the subclass does not override this method, then the default behavior is + * to return {@link IStatus#OK OK} if and only if the includepath container can + * be updated (see {@link #canUpdateJsGlobalScopeContainer(IPath, IJavaScriptProject)}). + *
+ * + * @param containerPath the path of the container which requires to be + * updated + * @param project the project for which the container is to be updated + * @return returns the access rules attribute status + * + */ + public IStatus getAccessRulesStatus(IPath containerPath, IJavaScriptProject project) { + + if (canUpdateJsGlobalScopeContainer(containerPath, project)) { + return Status.OK_STATUS; + } + return new JavaModelStatus(ATTRIBUTE_READ_ONLY); + } + + /** + * Returns the extra attribute status according to this initializer. + *+ * The returned {@link IStatus status} can have one of the following severities: + *
+ * The status message can contain more information. + *
+ * If the subclass does not override this method, then the default behavior is + * to return {@link IStatus#OK OK} if and only if the includepath container can + * be updated (see {@link #canUpdateJsGlobalScopeContainer(IPath, IJavaScriptProject)}). + *
+ * + * @param containerPath the path of the container which requires to be + * updated + * @param project the project for which the container is to be updated + * @param attributeKey the key of the extra attribute + * @return returns the extra attribute status + * @see IIncludePathAttribute + */ + public IStatus getAttributeStatus(IPath containerPath, IJavaScriptProject project, String attributeKey) { + + if (canUpdateJsGlobalScopeContainer(containerPath, project)) { + return Status.OK_STATUS; + } + return new JavaModelStatus(ATTRIBUTE_READ_ONLY); + } + + /** + * Returns the source attachment attribute status according to this initializer. + *+ * The returned {@link IStatus status} can have one of the following severities: + *
+ * The status message can contain more information. + *
+ * If the subclass does not override this method, then the default behavior is + * to return {@link IStatus#OK OK} if and only if the includepath container can + * be updated (see {@link #canUpdateJsGlobalScopeContainer(IPath, IJavaScriptProject)}). + *
+ * + * @param containerPath the path of the container which requires to be + * updated + * @param project the project for which the container is to be updated + * @return returns the source attachment attribute status + */ + public IStatus getSourceAttachmentStatus(IPath containerPath, IJavaScriptProject project) { + + if (canUpdateJsGlobalScopeContainer(containerPath, project)) { + return Status.OK_STATUS; + } + return new JavaModelStatus(ATTRIBUTE_READ_ONLY); + } + + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.IJsGlobalScopeContainerInitialzer#getInferenceID() + */ + public String getInferenceID() + { + return null; + } + + public void removeFromProject(IJavaScriptProject project) {} + +} + diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JsGlobalScopeVariableInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JsGlobalScopeVariableInitializer.java new file mode 100644 index 0000000..5d6540b --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/JsGlobalScopeVariableInitializer.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core; + +/** + * Abstract base implementation of all includepath variable initializers. + * Includepath variable initializers are used in conjunction with the + * "org.eclipse.wst.jsdt.core.JsGlobalScopeVariableInitializer" extension point. + *
+ * Clients should subclass this class to implement a specific includepath
+ * variable initializer. The subclass must have a public 0-argument
+ * constructor and a concrete implementation of initialize
.
+ *
+ * @see IIncludePathEntry
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class JsGlobalScopeVariableInitializer {
+
+ /**
+ * Creates a new includepath variable initializer.
+ */
+ public JsGlobalScopeVariableInitializer() {
+ // a includepath variable initializer must have a public 0-argument constructor
+ }
+
+ /**
+ * Binds a value to the workspace includepath variable with the given name,
+ * or fails silently if this cannot be done.
+ *
+ * A variable initializer is automatically activated whenever a variable value
+ * is needed and none has been recorded so far. The implementation of
+ * the initializer can set the corresponding variable using
+ *
+ * The possible options are :
+ * JavaScriptCore#setClasspathVariable
.
+ *
+ * @param variable the name of the workspace includepath variable
+ * that requires a binding
+ *
+ * @see JavaScriptCore#getIncludepathVariable(String)
+ * @see JavaScriptCore#setIncludepathVariable(String, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
+ * @see JavaScriptCore#setIncludepathVariables(String[], org.eclipse.core.runtime.IPath[], org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public abstract void initialize(String variable);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/LibrarySuperType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/LibrarySuperType.java
new file mode 100644
index 0000000..67cc8e2
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/LibrarySuperType.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/**
+ *
+ */
+package org.eclipse.wst.jsdt.core;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ *
+ */
+public class LibrarySuperType {
+ IPath cpEntry;
+ String superTypeName;
+ String libraryName;
+ IJavaScriptProject javaProject;
+
+ public static final String SUPER_TYPE_CONTAINER= "org.eclipse.wst.jsdt.ui.superType.container"; //$NON-NLS-1$
+ public static final String SUPER_TYPE_NAME= "org.eclipse.wst.jsdt.ui.superType.name"; //$NON-NLS-1$
+
+ /* Only one superTypeName per instance so enforce that */
+ public LibrarySuperType(IPath classPathEntry, IJavaScriptProject project, String superTypeName) {
+ this.cpEntry = classPathEntry;
+ this.superTypeName = superTypeName;
+ this.javaProject = project;
+ this.libraryName = initLibraryName();
+
+ }
+
+ public LibrarySuperType(String classPathEntry, IJavaScriptProject project, String superTypeName) {
+ this(new Path(classPathEntry),project,superTypeName);
+ }
+ /* Construct parent */
+ public LibrarySuperType(IPath classPathEntry, IJavaScriptProject project) {
+ this(classPathEntry,project, null);
+ }
+
+ public IPath getRawContainerPath() {
+ return cpEntry;
+ }
+
+ public boolean hasChildren() {
+ /* defined super type meeans I'm a child */
+ if(superTypeName!=null) return false;
+ JsGlobalScopeContainerInitializer init = getContainerInitializer();
+ if (init == null) return false;
+ String[] availableSuperTypes = init.containerSuperTypes();
+ return availableSuperTypes!=null && availableSuperTypes.length>0;
+ }
+
+ public LibrarySuperType[] getChildren() {
+ if(superTypeName!=null) return new LibrarySuperType[0];
+ return getFlatLibrarySuperTypes(cpEntry,javaProject);
+ }
+
+ public LibrarySuperType getParent() {
+ if(superTypeName==null) return null;
+ return new LibrarySuperType(cpEntry,javaProject, null);
+ }
+
+ public boolean isParent() {
+ return getParent()==null;
+ }
+
+ public JsGlobalScopeContainerInitializer getContainerInitializer() {
+ return getContainerInitializer(cpEntry);
+ }
+
+ public IIncludePathEntry[] getClasspathEntries() {
+ IJsGlobalScopeContainer container=null;
+ try {
+ container = JavaScriptCore.getJsGlobalScopeContainer(this.cpEntry, this.javaProject);
+ } catch (JavaScriptModelException ex) {
+ // TODO Auto-generated catch block
+ ex.printStackTrace();
+ }
+ if(container!=null) return container.getIncludepathEntries();
+
+ return new IIncludePathEntry[0];
+ }
+
+ private static LibrarySuperType[] getFlatLibrarySuperTypes(IPath classPathEntry, IJavaScriptProject javaProject) {
+ JsGlobalScopeContainerInitializer init = getContainerInitializer(classPathEntry);
+ if (init == null) return new LibrarySuperType[0];
+ String[] availableSuperTypes = init.containerSuperTypes();
+ LibrarySuperType[] libSupers = new LibrarySuperType[availableSuperTypes.length];
+ for (int i = 0; i < availableSuperTypes.length; i++) {
+ libSupers[i] = new LibrarySuperType(classPathEntry, javaProject, availableSuperTypes[i]);
+ }
+ return libSupers;
+ }
+
+ public String getSuperTypeName() {
+ return superTypeName;
+ }
+
+ public String getLibraryName() {
+ return libraryName;
+ }
+
+ private String initLibraryName() {
+ JsGlobalScopeContainerInitializer init = getContainerInitializer();
+
+ /* parent node */
+ if(superTypeName==null) {
+ if(init==null) {
+ return cpEntry.toString();
+ }
+ return init.getDescription();
+ }
+ Object parent = getParent();
+ if(!(parent instanceof LibrarySuperType)) return null;
+ return ((LibrarySuperType)parent).getLibraryName();
+ }
+
+ public String toString() {
+ //JsGlobalScopeContainerInitializer init = getContainerInitializer();
+
+ /* parent node */
+ if(isParent()) {
+ return getLibraryName();
+
+ }
+
+ return Messages.getString("LibrarySuperType.0", new Object[]{superTypeName, getLibraryName()}); //$NON-NLS-1$
+ }
+
+ public boolean equals(Object o) {
+ if(!(o instanceof LibrarySuperType)) return false;
+
+ LibrarySuperType other = (LibrarySuperType)o;
+
+
+
+ if(other.cpEntry!=null && !other.cpEntry.equals(cpEntry)) {
+ return false;
+ }
+
+ if((other.superTypeName==superTypeName)) {
+ return true;
+ }
+
+ if(other.superTypeName!=null && superTypeName!=null) {
+ return other.superTypeName.equals(superTypeName);
+ }
+
+ return false;
+ }
+
+ public IPackageFragment[] getPackageFragments(){
+ IIncludePathEntry[] entries = getClasspathEntries();
+ ArrayList allFrags = new ArrayList();
+
+ try {
+ for(int i = 0;i
+ *
+ *
+ * For a complete description of the configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
+ * This class provides static methods and constants only; it is not intended to be + * instantiated or subclassed by clients. + *
+ * + * @see JavaScriptCore#setOptions(java.util.Hashtable) + * @see JavaScriptCore#getDefaultOptions() + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class NamingConventions { + private static final char[] GETTER_BOOL_NAME = "is".toCharArray(); //$NON-NLS-1$ + private static final char[] GETTER_NAME = "get".toCharArray(); //$NON-NLS-1$ + private static final char[] SETTER_NAME = "set".toCharArray(); //$NON-NLS-1$ + + static class NamingRequestor implements INamingRequestor { + private final static int SIZE = 10; + + // for acceptNameWithPrefixAndSuffix + private char[][] firstPrefixAndFirstSuffixResults = new char[SIZE][]; + private int firstPrefixAndFirstSuffixResultsCount = 0; + private char[][] firstPrefixAndSuffixResults = new char[SIZE][]; + private int firstPrefixAndSuffixResultsCount = 0; + private char[][] prefixAndFirstSuffixResults = new char[SIZE][]; + private int prefixAndFirstSuffixResultsCount = 0; + private char[][] prefixAndSuffixResults = new char[SIZE][]; + private int prefixAndSuffixResultsCount = 0; + + // for acceptNameWithPrefix + private char[][] firstPrefixResults = new char[SIZE][]; + private int firstPrefixResultsCount = 0; + private char[][] prefixResults = new char[SIZE][]; + private int prefixResultsCount = 0; + + // for acceptNameWithSuffix + private char[][] firstSuffixResults = new char[SIZE][]; + private int firstSuffixResultsCount = 0; + private char[][] suffixResults = new char[SIZE][]; + private int suffixResultsCount = 0; + + // for acceptNameWithoutPrefixAndSuffix + private char[][] otherResults = new char[SIZE][]; + private int otherResultsCount = 0; + public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters) { + if(isFirstPrefix && isFirstSuffix) { + int length = this.firstPrefixAndFirstSuffixResults.length; + if(length == this.firstPrefixAndFirstSuffixResultsCount) { + System.arraycopy( + this.firstPrefixAndFirstSuffixResults, + 0, + this.firstPrefixAndFirstSuffixResults = new char[length * 2][], + 0, + length); + } + this.firstPrefixAndFirstSuffixResults[this.firstPrefixAndFirstSuffixResultsCount++] = name; + } else if (isFirstPrefix) { + int length = this.firstPrefixAndSuffixResults.length; + if(length == this.firstPrefixAndSuffixResultsCount) { + System.arraycopy( + this.firstPrefixAndSuffixResults, + 0, + this.firstPrefixAndSuffixResults = new char[length * 2][], + 0, + length); + } + this.firstPrefixAndSuffixResults[this.firstPrefixAndSuffixResultsCount++] = name; + } else if(isFirstSuffix) { + int length = this.prefixAndFirstSuffixResults.length; + if(length == this.prefixAndFirstSuffixResultsCount) { + System.arraycopy( + this.prefixAndFirstSuffixResults, + 0, + this.prefixAndFirstSuffixResults = new char[length * 2][], + 0, + length); + } + this.prefixAndFirstSuffixResults[this.prefixAndFirstSuffixResultsCount++] = name; + } else { + int length = this.prefixAndSuffixResults.length; + if(length == this.prefixAndSuffixResultsCount) { + System.arraycopy( + this.prefixAndSuffixResults, + 0, + this.prefixAndSuffixResults = new char[length * 2][], + 0, + length); + } + this.prefixAndSuffixResults[this.prefixAndSuffixResultsCount++] = name; + } + } + + public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters) { + if(isFirstPrefix) { + int length = this.firstPrefixResults.length; + if(length == this.firstPrefixResultsCount) { + System.arraycopy( + this.firstPrefixResults, + 0, + this.firstPrefixResults = new char[length * 2][], + 0, + length); + } + this.firstPrefixResults[this.firstPrefixResultsCount++] = name; + } else{ + int length = this.prefixResults.length; + if(length == this.prefixResultsCount) { + System.arraycopy( + this.prefixResults, + 0, + this.prefixResults = new char[length * 2][], + 0, + length); + } + this.prefixResults[this.prefixResultsCount++] = name; + } + } + + public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters) { + if(isFirstSuffix) { + int length = this.firstSuffixResults.length; + if(length == this.firstSuffixResultsCount) { + System.arraycopy( + this.firstSuffixResults, + 0, + this.firstSuffixResults = new char[length * 2][], + 0, + length); + } + this.firstSuffixResults[this.firstSuffixResultsCount++] = name; + } else { + int length = this.suffixResults.length; + if(length == this.suffixResultsCount) { + System.arraycopy( + this.suffixResults, + 0, + this.suffixResults = new char[length * 2][], + 0, + length); + } + this.suffixResults[this.suffixResultsCount++] = name; + } + } + + public void acceptNameWithoutPrefixAndSuffix(char[] name, int reusedCharacters) { + int length = this.otherResults.length; + if(length == this.otherResultsCount) { + System.arraycopy( + this.otherResults, + 0, + this.otherResults = new char[length * 2][], + 0, + length); + } + this.otherResults[this.otherResultsCount++] = name; + } + public char[][] getResults(){ + int count = + this.firstPrefixAndFirstSuffixResultsCount + + this.firstPrefixAndSuffixResultsCount + + this.prefixAndFirstSuffixResultsCount + + this.prefixAndSuffixResultsCount + + this.firstPrefixResultsCount + + this.prefixResultsCount + + this.firstSuffixResultsCount + + this.suffixResultsCount + + this.otherResultsCount; + + char[][] results = new char[count][]; + + int index = 0; + System.arraycopy(this.firstPrefixAndFirstSuffixResults, 0, results, index, this.firstPrefixAndFirstSuffixResultsCount); + index += this.firstPrefixAndFirstSuffixResultsCount; + System.arraycopy(this.firstPrefixAndSuffixResults, 0, results, index, this.firstPrefixAndSuffixResultsCount); + index += this.firstPrefixAndSuffixResultsCount; + System.arraycopy(this.prefixAndFirstSuffixResults, 0, results, index, this.prefixAndFirstSuffixResultsCount); + index += this.prefixAndFirstSuffixResultsCount; + System.arraycopy(this.prefixAndSuffixResults, 0, results, index, this.prefixAndSuffixResultsCount); + index += this.prefixAndSuffixResultsCount; + System.arraycopy(this.firstPrefixResults, 0, results, index, this.firstPrefixResultsCount); + index += this.firstPrefixResultsCount; + System.arraycopy(this.prefixResults, 0, results, index, this.prefixResultsCount); + index += this.prefixResultsCount; + System.arraycopy(this.firstSuffixResults, 0, results, index, this.firstSuffixResultsCount); + index += this.firstSuffixResultsCount; + System.arraycopy(this.suffixResults, 0, results, index, this.suffixResultsCount); + index += this.suffixResultsCount; + System.arraycopy(this.otherResults, 0, results, index, this.otherResultsCount); + + return results; + } + } + + + private NamingConventions() { + // Not instantiable + } + + private static char[] removePrefixAndSuffix(char[] name, char[][] prefixes, char[][] suffixes) { + // remove longer prefix + char[] withoutPrefixName = name; + if (prefixes != null) { + int bestLength = 0; + for (int i= 0; i < prefixes.length; i++) { + char[] prefix = prefixes[i]; + if (CharOperation.prefixEquals(prefix, name)) { + int currLen = prefix.length; + boolean lastCharIsLetter = ScannerHelper.isLetter(prefix[currLen - 1]); + if(!lastCharIsLetter || (lastCharIsLetter && name.length > currLen && ScannerHelper.isUpperCase(name[currLen]))) { + if (bestLength < currLen && name.length != currLen) { + withoutPrefixName = CharOperation.subarray(name, currLen, name.length); + bestLength = currLen; + } + } + } + } + } + + // remove longer suffix + char[] withoutSuffixName = withoutPrefixName; + if(suffixes != null) { + int bestLength = 0; + for (int i = 0; i < suffixes.length; i++) { + char[] suffix = suffixes[i]; + if(CharOperation.endsWith(withoutPrefixName, suffix)) { + int currLen = suffix.length; + if(bestLength < currLen && withoutPrefixName.length != currLen) { + withoutSuffixName = CharOperation.subarray(withoutPrefixName, 0, withoutPrefixName.length - currLen); + bestLength = currLen; + } + } + } + } + + withoutSuffixName[0] = ScannerHelper.toLowerCase(withoutSuffixName[0]); + return withoutSuffixName; + } + + /** + * Remove prefix and suffix from an argument name. + *
+ * If argument name prefix is pre
and argument name suffix is suf
+ * then for an argument named preArgsuf
the result of this method is arg
.
+ * If there is no prefix or suffix defined in JavaScriptCore options the result is the unchanged
+ * name preArgsuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_ARGUMENT_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_ARGUMENT_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
+ * If argument name prefix is pre
and argument name suffix is suf
+ * then for an argument named preArgsuf
the result of this method is arg
.
+ * If there is no prefix or suffix defined in JavaScriptCore options the result is the unchanged
+ * name preArgsuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_ARGUMENT_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_ARGUMENT_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
+ * If field name prefix is pre
and field name suffix is suf
+ * then for a field named preFieldsuf
the result of this method is field
.
+ * If there is no prefix or suffix defined in JavaScriptCore options the result is the unchanged
+ * name preFieldsuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES} } , + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @return char[] the name without prefix and suffix.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static char[] removePrefixAndSuffixForFieldName(IJavaScriptProject javaProject, char[] fieldName, int modifiers) {
+ boolean isStatic = Flags.isStatic(modifiers);
+ AssistOptions assistOptions = new AssistOptions(javaProject.getOptions(true));
+ return removePrefixAndSuffix(
+ fieldName,
+ isStatic ? assistOptions.staticFieldPrefixes : assistOptions.fieldPrefixes,
+ isStatic ? assistOptions.staticFieldSuffixes : assistOptions.fieldSuffixes);
+ }
+
+ /**
+ * Remove prefix and suffix from a field name.
+ *
+ * If field name prefix is pre
and field name suffix is suf
+ * then for a field named preFieldsuf
the result of this method is field
.
+ * If there is no prefix or suffix defined in JavaScriptCore options the result is the unchanged
+ * name preFieldsuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @return char[] the name without prefix and suffix.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static String removePrefixAndSuffixForFieldName(IJavaScriptProject javaProject, String fieldName, int modifiers) {
+ return String.valueOf(removePrefixAndSuffixForFieldName(javaProject, fieldName.toCharArray(), modifiers));
+ }
+ /**
+ * Remove prefix and suffix from a local variable name.
+ *
+ * If local variable name prefix is pre
and local variable name suffix is suf
+ * then for a local variable named preLocalsuf
the result of this method is local
.
+ * If there is no prefix or suffix defined in JavaScriptCore options the result is the unchanged
+ * name preLocalsuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_LOCAL_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_LOCAL_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
+ * If local variable name prefix is pre
and local variable name suffix is suf
+ * then for a local variable named preLocalsuf
the result of this method is local
.
+ * If there is no prefix or suffix defined in JavaScriptCore options the result is the unchanged
+ * name preLocalsuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_LOCAL_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_LOCAL_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
+ * If the type of the argument is TypeName
, the prefix for argument is pre
+ * and the suffix for argument is suf
then the proposed names are preTypeNamesuf
+ * and preNamesuf
. If there is no prefix or suffix the proposals are typeName
+ * and name
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_ARGUMENT_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_ARGUMENT_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
null
if there is no excluded names.
+ * @return char[][] an array of names.
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static char[][] suggestArgumentNames(IJavaScriptProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames) {
+ NamingRequestor requestor = new NamingRequestor();
+ InternalNamingConventions.suggestArgumentNames(
+ javaProject,
+ packageName,
+ qualifiedTypeName,
+ dim,
+ null,
+ excludedNames,
+ requestor);
+
+ return requestor.getResults();
+ }
+
+ /**
+ * Suggest names for an argument. The name is computed from argument's type
+ * and possible prefixes or suffixes are added.
+ *
+ * If the type of the argument is TypeName
, the prefix for argument is pre
+ * and the suffix for argument is suf
then the proposed names are preTypeNamesuf
+ * and preNamesuf
. If there is no prefix or suffix the proposals are typeName
+ * and name
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_ARGUMENT_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_ARGUMENT_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
null
if there is no excluded names.
+ * @return char[][] an array of names.
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static String[] suggestArgumentNames(IJavaScriptProject javaProject, String packageName, String qualifiedTypeName, int dim, String[] excludedNames) {
+ return convertCharsToString(
+ suggestArgumentNames(
+ javaProject,
+ packageName!=null ? packageName.toCharArray() : null,
+ qualifiedTypeName!=null ? qualifiedTypeName.toCharArray():null,
+ dim,
+ convertStringToChars(excludedNames)));
+ }
+ /**
+ * Suggest names for a field. The name is computed from field's type
+ * and possible prefixes or suffixes are added.
+ *
+ * If the type of the field is TypeName
, the prefix for field is pre
+ * and the suffix for field is suf
then the proposed names are preTypeNamesuf
+ * and preNamesuf
. If there is no prefix or suffix the proposals are typeName
+ * and name
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} and for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @param excludedNames a list of names which cannot be suggested (already used names).
+ * Can be null
if there is no excluded names.
+ * @return char[][] an array of names.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static char[][] suggestFieldNames(IJavaScriptProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, int modifiers, char[][] excludedNames) {
+ NamingRequestor requestor = new NamingRequestor();
+ InternalNamingConventions.suggestFieldNames(
+ javaProject,
+ packageName,
+ qualifiedTypeName,
+ dim,
+ modifiers,
+ null,
+ excludedNames,
+ requestor);
+
+ return requestor.getResults();
+ }
+
+ /**
+ * Suggest names for a field. The name is computed from field's type
+ * and possible prefixes or suffixes are added.
+ *
+ * If the type of the field is TypeName
, the prefix for field is pre
+ * and the suffix for field is suf
then the proposed names are preTypeNamesuf
+ * and preNamesuf
. If there is no prefix or suffix the proposals are typeName
+ * and name
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} and for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @param excludedNames a list of names which cannot be suggested (already used names).
+ * Can be null
if there is no excluded names.
+ * @return char[][] an array of names.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static String[] suggestFieldNames(IJavaScriptProject javaProject, String packageName, String qualifiedTypeName, int dim, int modifiers, String[] excludedNames) {
+ return convertCharsToString(
+ suggestFieldNames(
+ javaProject,
+ packageName.toCharArray(),
+ qualifiedTypeName.toCharArray(),
+ dim,
+ modifiers,
+ convertStringToChars(excludedNames)));
+ }
+
+ /**
+ * Suggest names for a local variable. The name is computed from variable's type
+ * and possible prefixes or suffixes are added.
+ *
+ * If the type of the local variable is TypeName
, the prefix for local variable is pre
+ * and the suffix for local variable is suf
then the proposed names are preTypeNamesuf
+ * and preNamesuf
. If there is no prefix or suffix the proposals are typeName
+ * and name
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_LOCAL_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_LOCAL_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
null
if there is no excluded names.
+ * @return char[][] an array of names.
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static char[][] suggestLocalVariableNames(IJavaScriptProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames) {
+ NamingRequestor requestor = new NamingRequestor();
+ InternalNamingConventions.suggestLocalVariableNames(
+ javaProject,
+ packageName,
+ qualifiedTypeName,
+ dim,
+ null,
+ excludedNames,
+ requestor);
+
+ return requestor.getResults();
+ }
+
+ /**
+ * Suggest names for a local variable. The name is computed from variable's type
+ * and possible prefixes or suffixes are added.
+ *
+ * If the type of the local variable is TypeName
, the prefix for local variable is pre
+ * and the suffix for local variable is suf
then the proposed names are preTypeNamesuf
+ * and preNamesuf
. If there is no prefix or suffix the proposals are typeName
+ * and name
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_LOCAL_PREFIXES} and + * {@link JavaScriptCore#CODEASSIST_LOCAL_SUFFIXES}. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
null
if there is no excluded names.
+ * @return char[][] an array of names.
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static String[] suggestLocalVariableNames(IJavaScriptProject javaProject, String packageName, String qualifiedTypeName, int dim, String[] excludedNames) {
+ return convertCharsToString(
+ suggestLocalVariableNames(
+ javaProject,
+ packageName.toCharArray(),
+ qualifiedTypeName.toCharArray(),
+ dim,
+ convertStringToChars(excludedNames)));
+ }
+
+ /**
+ * Suggest name for a getter method. The name is computed from field's name
+ * and possible prefixes or suffixes are removed.
+ *
+ * If the field name is preFieldNamesuf
and the prefix for field is pre
and
+ * the suffix for field is suf
then the prosposed name is isFieldName
for boolean field or
+ * getFieldName
for others. If there is no prefix and suffix the proposal is isPreFieldNamesuf
+ * for boolean field or getPreFieldNamesuf
for others.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @param isBoolean true
if the field's type is boolean
+ * @param excludedNames a list of names which cannot be suggested (already used names).
+ * Can be null
if there is no excluded names.
+ * @return char[] a name.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static char[] suggestGetterName(IJavaScriptProject project, char[] fieldName, int modifiers, boolean isBoolean, char[][] excludedNames) {
+ if (isBoolean) {
+ char[] name = removePrefixAndSuffixForFieldName(project, fieldName, modifiers);
+ int prefixLen = GETTER_BOOL_NAME.length;
+ if (CharOperation.prefixEquals(GETTER_BOOL_NAME, name)
+ && name.length > prefixLen && ScannerHelper.isUpperCase(name[prefixLen])) {
+ return suggestNewName(name, excludedNames);
+ } else {
+ return suggestNewName(
+ CharOperation.concat(GETTER_BOOL_NAME, suggestAccessorName(project, fieldName, modifiers)),
+ excludedNames
+ );
+ }
+ } else {
+ return suggestNewName(
+ CharOperation.concat(GETTER_NAME, suggestAccessorName(project, fieldName, modifiers)),
+ excludedNames
+ );
+ }
+ }
+
+ /**
+ * Suggest name for a getter method. The name is computed from field's name
+ * and possible prefixes or suffixes are removed.
+ *
+ * If the field name is preFieldNamesuf
and the prefix for field is pre
and
+ * the suffix for field is suf
then the prosposed name is isFieldName
for boolean field or
+ * getFieldName
for others. If there is no prefix and suffix the proposal is isPreFieldNamesuf
+ * for boolean field or getPreFieldNamesuf
for others.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @param isBoolean true
if the field's type is boolean
+ * @param excludedNames a list of names which cannot be suggested (already used names).
+ * Can be null
if there is no excluded names.
+ * @return char[] a name.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static String suggestGetterName(IJavaScriptProject project, String fieldName, int modifiers, boolean isBoolean, String[] excludedNames) {
+ return String.valueOf(
+ suggestGetterName(
+ project,
+ fieldName.toCharArray(),
+ modifiers,
+ isBoolean,
+ convertStringToChars(excludedNames)));
+ }
+
+ /**
+ * Suggest name for a setter method. The name is computed from field's name
+ * and possible prefixes or suffixes are removed.
+ *
+ * If the field name is preFieldNamesuf
and the prefix for field is pre
and
+ * the suffix for field is suf
then the proposed name is setFieldName
.
+ * If there is no prefix and suffix the proposal is setPreFieldNamesuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @param isBoolean true
if the field's type is boolean
+ * @param excludedNames a list of names which cannot be suggested (already used names).
+ * Can be null
if there is no excluded names.
+ * @return char[] a name.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static char[] suggestSetterName(IJavaScriptProject project, char[] fieldName, int modifiers, boolean isBoolean, char[][] excludedNames) {
+
+ if (isBoolean) {
+ char[] name = removePrefixAndSuffixForFieldName(project, fieldName, modifiers);
+ int prefixLen = GETTER_BOOL_NAME.length;
+ if (CharOperation.prefixEquals(GETTER_BOOL_NAME, name)
+ && name.length > prefixLen && ScannerHelper.isUpperCase(name[prefixLen])) {
+ name = CharOperation.subarray(name, prefixLen, name.length);
+ return suggestNewName(
+ CharOperation.concat(SETTER_NAME, suggestAccessorName(project, name, modifiers)),
+ excludedNames
+ );
+ } else {
+ return suggestNewName(
+ CharOperation.concat(SETTER_NAME, suggestAccessorName(project, fieldName, modifiers)),
+ excludedNames
+ );
+ }
+ } else {
+ return suggestNewName(
+ CharOperation.concat(SETTER_NAME, suggestAccessorName(project, fieldName, modifiers)),
+ excludedNames
+ );
+ }
+ }
+
+ /**
+ * Suggest name for a setter method. The name is computed from field's name
+ * and possible prefixes or suffixes are removed.
+ *
+ * If the field name is preFieldNamesuf
and the prefix for field is pre
and
+ * the suffix for field is suf
then the proposed name is setFieldName
.
+ * If there is no prefix and suffix the proposal is setPreFieldNamesuf
.
+ *
+ * This method is affected by the following JavaScriptCore options : {@link JavaScriptCore#CODEASSIST_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_PREFIXES}, + * {@link JavaScriptCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field. + *
+ *
+ * For a complete description of these configurable options, see getDefaultOptions
.
+ * For programmaticaly change these options, see JavaScriptCore#setOptions()
.
+ *
Flags
.
+ * @param isBoolean true
if the field's type is boolean
+ * @param excludedNames a list of names which cannot be suggested (already used names).
+ * Can be null
if there is no excluded names.
+ * @return char[] a name.
+ * @see Flags
+ * @see JavaScriptCore#setOptions(java.util.Hashtable)
+ * @see JavaScriptCore#getDefaultOptions()
+ */
+ public static String suggestSetterName(IJavaScriptProject project, String fieldName, int modifiers, boolean isBoolean, String[] excludedNames) {
+ return String.valueOf(
+ suggestSetterName(
+ project,
+ fieldName.toCharArray(),
+ modifiers,
+ isBoolean,
+ convertStringToChars(excludedNames)));
+ }
+
+ private static char[] suggestAccessorName(IJavaScriptProject project, char[] fieldName, int modifiers) {
+ char[] name = removePrefixAndSuffixForFieldName(project, fieldName, modifiers);
+ if (name.length > 0 && ScannerHelper.isLowerCase(name[0])) {
+ name[0] = ScannerHelper.toUpperCase(name[0]);
+ }
+ return name;
+ }
+
+ private static char[] suggestNewName(char[] name, char[][] excludedNames){
+ if(excludedNames == null) {
+ return name;
+ }
+
+ char[] newName = name;
+ int count = 2;
+ int i = 0;
+ while (i < excludedNames.length) {
+ if(CharOperation.equals(newName, excludedNames[i], false)) {
+ newName = CharOperation.concat(name, String.valueOf(count++).toCharArray());
+ i = 0;
+ } else {
+ i++;
+ }
+ }
+ return newName;
+ }
+
+ private static String[] convertCharsToString(char[][] c) {
+ int length = c == null ? 0 : c.length;
+ String[] s = new String[length];
+ for (int i = 0; i < length; i++) {
+ s[i] = String.valueOf(c[i]);
+ }
+ return s;
+ }
+
+ private static char[][] convertStringToChars(String[] s) {
+ int length = s == null ? 0 : s.length;
+ char[][] c = new char[length][];
+ for (int i = 0; i < length; i++) {
+ if(s[i] == null) {
+ c[i] = CharOperation.NO_CHAR;
+ } else {
+ c[i] = s[i].toCharArray();
+ }
+ }
+ return c;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java
new file mode 100644
index 0000000..07c2dbb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/Signature.java
@@ -0,0 +1,1644 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * IBM Corporation - added J2SE 1.5 support
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.core.util.Util;
+
+
+/**
+ * Provides methods for encoding and decoding type and method signature strings.
+ * + * This class provides static methods and constants only; it is not intended to be + * instantiated or subclassed by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class Signature { + + /** + * Character constant indicating the semicolon in a signature. + * Value is';'
.
+ */
+ public static final char C_SEMICOLON = ';';
+
+ /**
+ * Character constant indicating the colon in a signature.
+ * Value is ':'
.
+ * 3.0
+ */
+ public static final char C_COLON = ':';
+
+ /**
+ * Character constant indicating result type void in a signature.
+ * Value is 'V'
.
+ */
+ public static final char C_VOID = 'V';
+
+
+ /**
+ * Character constant indicating any type in a signature.
+ * Value is 'A'
.
+ */
+ public static final char C_ANY = 'A';
+
+ /**
+ * Character constant indicating the dot in a signature.
+ * Value is '.'
.
+ */
+ public static final char C_DOT = '.';
+
+ /**
+ * Character constant indicating the dollar in a signature.
+ * Value is '$'
.
+ */
+ public static final char C_DOLLAR = '$';
+
+ /**
+ * Character constant indicating an array type in a signature.
+ * Value is '['
.
+ */
+ public static final char C_ARRAY = '[';
+
+ /**
+ * Character constant indicating the start of a resolved, named type in a
+ * signature. Value is 'L'
.
+ */
+ public static final char C_RESOLVED = 'L';
+
+
+ /**
+ * Character constant indicating a compilation unit.
+ * Value is 'X'
.
+ */
+ public static final char C_COMPILATION_UNIT = 'X';
+
+
+ /**
+ * Character constant indicating the start of an unresolved, named type in a
+ * signature. Value is 'Q'
.
+ */
+ public static final char C_UNRESOLVED = 'Q';
+
+ /**
+ * Character constant indicating the end of a named type in a signature.
+ * Value is ';'
.
+ */
+ public static final char C_NAME_END = ';';
+
+ /**
+ * Character constant indicating the start of a parameter type list in a
+ * signature. Value is '('
.
+ */
+ public static final char C_PARAM_START = '(';
+
+ /**
+ * Character constant indicating the end of a parameter type list in a
+ * signature. Value is ')'
.
+ */
+ public static final char C_PARAM_END = ')';
+
+ /** String constant for the signature of result type void.
+ * Value is "V"
.
+ */
+ public static final String SIG_VOID = "V"; //$NON-NLS-1$
+
+ public static final String SIG_ANY = "A"; //$NON-NLS-1$
+
+ public static final String SIG_COMPILATION_UNIT = "X"; //$NON-NLS-1$
+
+ /**
+ * Kind constant for a class type signature.
+ * @see #getTypeSignatureKind(String)
+ *
+ */
+ public static final int CLASS_TYPE_SIGNATURE = 1;
+
+ /**
+ * Kind constant for a base (primitive or void) type signature.
+ * @see #getTypeSignatureKind(String)
+ *
+ */
+ public static final int BASE_TYPE_SIGNATURE = 2;
+
+ /**
+ * Kind constant for an array type signature.
+ * @see #getTypeSignatureKind(String)
+ *
+ */
+ public static final int ARRAY_TYPE_SIGNATURE = 4;
+
+ private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
+ public static final char[] ANY = "any".toCharArray(); //$NON-NLS-1$
+
+private Signature() {
+ // Not instantiable
+}
+
+private static int checkName(char[] name, char[] typeName, int pos, int length) {
+ if (CharOperation.fragmentEquals(name, typeName, pos, true)) {
+ pos += name.length;
+ if (pos == length) return pos;
+ char currentChar = typeName[pos];
+ switch (currentChar) {
+ case ' ' :
+ case '.' :
+ case '[' :
+ case ',' :
+ return pos;
+ default:
+ if (ScannerHelper.isWhitespace(currentChar))
+ return pos;
+
+ }
+ }
+ return -1;
+}
+
+/**
+ * Creates a new type signature with the given amount of array nesting added
+ * to the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @param arrayCount the desired number of levels of array nesting
+ * @return the encoded array type signature
+ *
+ *
+ */
+public static char[] createArraySignature(char[] typeSignature, int arrayCount) {
+ if (arrayCount == 0) return typeSignature;
+ int sigLength = typeSignature.length;
+ char[] result = new char[arrayCount + sigLength];
+ for (int i = 0; i < arrayCount; i++) {
+ result[i] = C_ARRAY;
+ }
+ System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
+ return result;
+}
+/**
+ * Creates a new type signature with the given amount of array nesting added
+ * to the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @param arrayCount the desired number of levels of array nesting
+ * @return the encoded array type signature
+ */
+public static String createArraySignature(String typeSignature, int arrayCount) {
+ return new String(createArraySignature(typeSignature.toCharArray(), arrayCount));
+}
+
+/**
+ * Creates a method signature from the given parameter and return type
+ * signatures. The encoded method signature is dot-based.
+ *
+ * @param parameterTypes the list of parameter type signatures
+ * @param returnType the return type signature
+ * @return the encoded method signature
+ *
+ *
+ */
+public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) {
+ int parameterTypesLength = parameterTypes.length;
+ int parameterLength = 0;
+ for (int i = 0; i < parameterTypesLength; i++) {
+ parameterLength += parameterTypes[i].length;
+
+ }
+ int returnTypeLength = returnType.length;
+ char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
+ result[0] = C_PARAM_START;
+ int index = 1;
+ for (int i = 0; i < parameterTypesLength; i++) {
+ char[] parameterType = parameterTypes[i];
+ int length = parameterType.length;
+ System.arraycopy(parameterType, 0, result, index, length);
+ index += length;
+ }
+ result[index] = C_PARAM_END;
+ System.arraycopy(returnType, 0, result, index+1, returnTypeLength);
+ return result;
+}
+
+/**
+ * Creates a method signature from the given parameter and return type
+ * signatures. The encoded method signature is dot-based. This method
+ * is equivalent to
+ * createMethodSignature(parameterTypes, returnType)
.
+ *
+ * @param parameterTypes the list of parameter type signatures
+ * @param returnType the return type signature
+ * @return the encoded method signature
+ * @see Signature#createMethodSignature(char[][], char[])
+ */
+public static String createMethodSignature(String[] parameterTypes, String returnType) {
+ int parameterTypesLenth = parameterTypes.length;
+ char[][] parameters = new char[parameterTypesLenth][];
+ for (int i = 0; i < parameterTypesLenth; i++) {
+ parameters[i] = parameterTypes[i].toCharArray();
+ }
+ return new String(createMethodSignature(parameters, returnType.toCharArray()));
+}
+
+/**
+ * Creates a new type signature from the given type name encoded as a character
+ * array. The type name may contain primitive types, array types or parameterized types.
+ * This method is equivalent to
+ * createTypeSignature(new String(typeName),isResolved)
, although
+ * more efficient for callers with character arrays rather than strings. If the
+ * type name is qualified, then it is expected to be dot-based.
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved true
if the type name is to be considered
+ * resolved (for example, a type name from a binary class file), and
+ * false
if the type name is to be considered unresolved
+ * (for example, a type name found in source code)
+ * @return the encoded type signature
+ * @see #createTypeSignature(java.lang.String,boolean)
+ */
+public static String createTypeSignature(char[] typeName, boolean isResolved) {
+ return new String(createCharArrayTypeSignature(typeName, isResolved));
+}
+
+/**
+ * Creates a new type signature from the given type name encoded as a character
+ * array. The type name may contain primitive types or array types or parameterized types.
+ * This method is equivalent to
+ * createTypeSignature(new String(typeName),isResolved).toCharArray()
,
+ * although more efficient for callers with character arrays rather than strings.
+ * If the type name is qualified, then it is expected to be dot-based.
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved true
if the type name is to be considered
+ * resolved (for example, a type name from a binary class file), and
+ * false
if the type name is to be considered unresolved
+ * (for example, a type name found in source code)
+ * @return the encoded type signature
+ * @see #createTypeSignature(java.lang.String,boolean)
+ *
+ *
+ */
+public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) {
+ if (typeName == null || typeName.length == 0)
+ {
+ return new char[]{C_ANY};
+ }
+
+ int length = typeName.length;
+ StringBuffer buffer = new StringBuffer(5);
+ int pos = encodeTypeSignature(typeName, 0, isResolved, length, buffer);
+ pos = consumeWhitespace(typeName, pos, length);
+ if (pos < length) throw new IllegalArgumentException(new String(typeName));
+ char[] result = new char[length = buffer.length()];
+ buffer.getChars(0, length, result, 0);
+ return result;
+}
+private static int consumeWhitespace(char[] typeName, int pos, int length) {
+ while (pos < length) {
+ char currentChar = typeName[pos];
+ if (currentChar != ' ' && !CharOperation.isWhitespace(currentChar)) {
+ break;
+ }
+ pos++;
+ }
+ return pos;
+}
+private static int encodeQualifiedName(char[] typeName, int pos, int length, StringBuffer buffer) {
+ int count = 0;
+ char lastAppendedChar = 0;
+ nameLoop: while (pos < length) {
+ char currentChar = typeName[pos];
+ switch (currentChar) {
+ case '[' :
+ case ',' :
+ break nameLoop;
+ case '.' :
+ buffer.append(C_DOT);
+ lastAppendedChar = C_DOT;
+ count++;
+ break;
+ default:
+ if (currentChar == ' ' || ScannerHelper.isWhitespace(currentChar)) {
+ if (lastAppendedChar == C_DOT) { // allow spaces after a dot
+ pos = consumeWhitespace(typeName, pos, length) - 1; // will be incremented
+ break;
+ }
+ // allow spaces before a dot
+ int checkPos = checkNextChar(typeName, '.', pos, length, true);
+ if (checkPos > 0) {
+ buffer.append(C_DOT); // process dot immediately to avoid one iteration
+ lastAppendedChar = C_DOT;
+ count++;
+ pos = checkPos;
+ break;
+ }
+ break nameLoop;
+ }
+ buffer.append(currentChar);
+ lastAppendedChar = currentChar;
+ count++;
+ break;
+ }
+ pos++;
+ }
+ if (count == 0) throw new IllegalArgumentException(new String(typeName));
+ return pos;
+}
+
+private static int encodeArrayDimension(char[] typeName, int pos, int length, StringBuffer buffer) {
+ int checkPos;
+ while (pos < length && (checkPos = checkNextChar(typeName, '[', pos, length, true)) > 0) {
+ pos = checkNextChar(typeName, ']', checkPos, length, false);
+ buffer.append(C_ARRAY);
+ }
+ return pos;
+}
+private static int checkArrayDimension(char[] typeName, int pos, int length) {
+ int genericBalance = 0;
+ while (pos < length) {
+ switch(typeName[pos]) {
+ case ',' :
+ if (genericBalance == 0) return -1;
+ break;
+ case '[':
+ if (genericBalance == 0) {
+ return pos;
+ }
+ }
+ pos++;
+ }
+ return -1;
+}
+private static int checkNextChar(char[] typeName, char expectedChar, int pos, int length, boolean isOptional) {
+ pos = consumeWhitespace(typeName, pos, length);
+ if (pos < length && typeName[pos] == expectedChar)
+ return pos + 1;
+ if (!isOptional) throw new IllegalArgumentException(new String(typeName));
+ return -1;
+}
+
+private static int encodeTypeSignature(char[] typeName, int start, boolean isResolved, int length, StringBuffer buffer) {
+ int pos = start;
+ pos = consumeWhitespace(typeName, pos, length);
+ if (pos >= length) throw new IllegalArgumentException(new String(typeName));
+ int checkPos;
+ char currentChar = typeName[pos];
+ switch (currentChar) {
+ // primitive type?
+ case 'v':
+ checkPos = checkName(VOID, typeName, pos, length);
+ if (checkPos > 0) {
+ pos = encodeArrayDimension(typeName, checkPos, length, buffer);
+ buffer.append(C_VOID);
+ return pos;
+ }
+ break;
+ }
+ // non primitive type
+ checkPos = checkArrayDimension(typeName, pos, length);
+ int end;
+ if (checkPos > 0) {
+ end = encodeArrayDimension(typeName, checkPos, length, buffer);
+ } else {
+ end = -1;
+ }
+ buffer.append(isResolved ? C_RESOLVED : C_UNRESOLVED);
+ while (true) { // loop on qualifiedName[+ * For example: + *
+ *
+ * createTypeSignature("int", hucairz) -> "I"
+ * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
+ * createTypeSignature("String", false) -> "QString;"
+ * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
+ * createTypeSignature("int []", false) -> "[I"
+ *
+ *
+ *
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved true
if the type name is to be considered
+ * resolved (for example, a type name from a binary class file), and
+ * false
if the type name is to be considered unresolved
+ * (for example, a type name found in source code)
+ * @return the encoded type signature
+ */
+public static String createTypeSignature(String typeName, boolean isResolved) {
+ return createTypeSignature(typeName == null ? null : typeName.toCharArray(), isResolved);
+}
+
+/**
+ * Returns the array count (array nesting depth) of the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @return the array nesting depth, or 0 if not an array
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ *
+ *
+ */
+public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException {
+ try {
+ int count = 0;
+ while (typeSignature[count] == C_ARRAY) {
+ ++count;
+ }
+ return count;
+ } catch (ArrayIndexOutOfBoundsException e) { // signature is syntactically incorrect if last character is C_ARRAY
+ throw new IllegalArgumentException();
+ }
+}
+/**
+ * Returns the array count (array nesting depth) of the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @return the array nesting depth, or 0 if not an array
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ */
+public static int getArrayCount(String typeSignature) throws IllegalArgumentException {
+ return getArrayCount(typeSignature.toCharArray());
+}
+/**
+ * Returns the type signature without any array nesting.
+ * + * For example: + *
+ *
+ * getElementType({'[', '[', 'I'}) --> {'I'}.
+ *
+ *
+ *
+ *
+ * @param typeSignature the type signature
+ * @return the type signature without arrays
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ *
+ *
+ */
+public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException {
+ int count = getArrayCount(typeSignature);
+ if (count == 0) return typeSignature;
+ int length = typeSignature.length;
+ char[] result = new char[length-count];
+ System.arraycopy(typeSignature, count, result, 0, length-count);
+ return result;
+}
+/**
+ * Returns the type signature without any array nesting.
+ * + * For example: + *
+ *
+ * getElementType("[[I") --> "I".
+ *
+ *
+ *
+ *
+ * @param typeSignature the type signature
+ * @return the type signature without arrays
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ */
+public static String getElementType(String typeSignature) throws IllegalArgumentException {
+ return new String(getElementType(typeSignature.toCharArray()));
+}
+/**
+ * Returns the number of parameter types in the given method signature.
+ *
+ * @param methodSignature the method signature
+ * @return the number of parameters
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ *
+ */
+public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException {
+ if (methodSignature==null)
+ return 0;
+ try {
+ int count = 0;
+ int i = CharOperation.indexOf(C_PARAM_START, methodSignature);
+ if (i < 0) {
+ throw new IllegalArgumentException();
+ } else {
+ i++;
+ }
+ for (;;) {
+ if (methodSignature[i] == C_PARAM_END) {
+ return count;
+ }
+ int e= Util.scanTypeSignature(methodSignature, i);
+ if (e < 0) {
+ throw new IllegalArgumentException();
+ } else {
+ i = e + 1;
+ }
+ count++;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException();
+ }
+}
+
+/**
+ * Returns the kind of type signature encoded by the given string.
+ *
+ * @param typeSignature the type signature string
+ * @return the kind of type signature; one of the kind constants:
+ * {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
+ * {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE},
+ * or {@link #CAPTURE_TYPE_SIGNATURE}
+ * @exception IllegalArgumentException if this is not a type signature
+ *
+ */
+public static int getTypeSignatureKind(char[] typeSignature) {
+ // need a minimum 1 char
+ if (typeSignature.length < 1) {
+ throw new IllegalArgumentException();
+ }
+ char c = typeSignature[0];
+ switch (c) {
+ case C_ARRAY :
+ return ARRAY_TYPE_SIGNATURE;
+ case C_RESOLVED :
+ case C_UNRESOLVED :
+ return CLASS_TYPE_SIGNATURE;
+ case C_VOID :
+ case C_ANY :
+ return BASE_TYPE_SIGNATURE;
+ default :
+ throw new IllegalArgumentException();
+ }
+}
+
+/**
+ * Returns the kind of type signature encoded by the given string.
+ *
+ * @param typeSignature the type signature string
+ * @return the kind of type signature; one of the kind constants:
+ * {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
+ * {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE},
+ * or {@link #CAPTURE_TYPE_SIGNATURE}
+ * @exception IllegalArgumentException if this is not a type signature
+ *
+ */
+public static int getTypeSignatureKind(String typeSignature) {
+ if (typeSignature.length() < 1) {
+ // uknown return type
+ return BASE_TYPE_SIGNATURE;
+ }
+ char c = typeSignature.charAt(0);
+ switch (c) {
+ case C_ARRAY :
+ return ARRAY_TYPE_SIGNATURE;
+ case C_RESOLVED :
+ case C_UNRESOLVED :
+ return CLASS_TYPE_SIGNATURE;
+ case C_VOID :
+ case C_ANY :
+
+ return BASE_TYPE_SIGNATURE;
+ default :
+ throw new IllegalArgumentException();
+ }
+}
+
+/**
+ * Returns the number of parameter types in the given method signature.
+ *
+ * @param methodSignature the method signature
+ * @return the number of parameters
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ */
+public static int getParameterCount(String methodSignature) throws IllegalArgumentException {
+ return getParameterCount(methodSignature.toCharArray());
+}
+
+/**
+ * Extracts the parameter type signatures from the given method signature.
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of parameter type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ * incorrect
+ *
+ *
+ */
+public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException {
+ try {
+ int count = getParameterCount(methodSignature);
+ char[][] result = new char[count][];
+ if (count == 0) {
+ return result;
+ }
+ int i = CharOperation.indexOf(C_PARAM_START, methodSignature);
+ if (i < 0) {
+ throw new IllegalArgumentException();
+ } else {
+ i++;
+ }
+ int t = 0;
+ for (;;) {
+ if (methodSignature[i] == C_PARAM_END) {
+ return result;
+ }
+ int e = Util.scanTypeSignature(methodSignature, i);
+ if (e < 0) {
+ throw new IllegalArgumentException();
+ }
+ result[t] = CharOperation.subarray(methodSignature, i, e + 1);
+ t++;
+ i = e + 1;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException();
+ }
+}
+
+/**
+ * Extracts the parameter type signatures from the given method signature.
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of parameter type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ * incorrect
+ */
+public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException {
+ char[][] parameterTypes = getParameterTypes(methodSignature.toCharArray());
+ return CharOperation.toStrings(parameterTypes);
+}
+
+/**
+ * Extracts the type variable name from the given formal type parameter
+ * signature. The signature is expected to be dot-based.
+ *
+ * @param formalTypeParameterSignature the formal type parameter signature
+ * @return the name of the type variable
+ * @exception IllegalArgumentException if the signature is syntactically
+ * incorrect
+ *
+ */
+public static String getTypeVariable(String formalTypeParameterSignature) throws IllegalArgumentException {
+ return new String(getTypeVariable(formalTypeParameterSignature.toCharArray()));
+}
+
+/**
+ * Extracts the type variable name from the given formal type parameter
+ * signature. The signature is expected to be dot-based.
+ *
+ * @param formalTypeParameterSignature the formal type parameter signature
+ * @return the name of the type variable
+ * @exception IllegalArgumentException if the signature is syntactically
+ * incorrect
+ *
+ */
+public static char[] getTypeVariable(char[] formalTypeParameterSignature) throws IllegalArgumentException {
+ int p = CharOperation.indexOf(C_COLON, formalTypeParameterSignature);
+ if (p < 0) {
+ // no ":" means can't be a formal type parameter signature
+ throw new IllegalArgumentException();
+ }
+ return CharOperation.subarray(formalTypeParameterSignature, 0, p);
+}
+
+/**
+ * Returns a char array containing all but the last segment of the given
+ * dot-separated qualified name. Returns the empty char array if it is not qualified.
+ * + * For example: + *
+ *
+ * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
+ * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
+ * getQualifier({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l'}
+ *
+ *
+ *
+ *
+ * @param name the name
+ * @return the qualifier prefix, or the empty char array if the name contains no
+ * dots
+ * @exception NullPointerException if name is null
+ *
+ */
+public static char[] getQualifier(char[] name) {
+ int lastDot = CharOperation.lastIndexOf(C_DOT, name, 0, name.length-1);
+ if (lastDot == -1) {
+ return CharOperation.NO_CHAR;
+ }
+ return CharOperation.subarray(name, 0, lastDot);
+}
+/**
+ * Returns a string containing all but the last segment of the given
+ * dot-separated qualified name. Returns the empty string if it is not qualified.
+ * + * For example: + *
+ *
+ * getQualifier("java.lang.Object") -> "java.lang"
+ * getQualifier("Outer.Inner") -> "Outer"
+ * getQualifier("java.util.List<java.lang.String>") -> "java.util"
+ *
+ *
+ *
+ *
+ * @param name the name
+ * @return the qualifier prefix, or the empty string if the name contains no
+ * dots
+ * @exception NullPointerException if name is null
+ */
+public static String getQualifier(String name) {
+ char[] qualifier = getQualifier(name.toCharArray());
+ if (qualifier.length == 0) return org.eclipse.wst.jsdt.internal.compiler.util.Util.EMPTY_STRING;
+ return new String(qualifier);
+}
+/**
+ * Extracts the return type from the given method signature. The method signature is
+ * expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the type signature of the return type
+ * @exception IllegalArgumentException if the signature is syntactically
+ * incorrect
+ *
+ *
+ */
+public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException {
+ // skip type parameters
+ if (methodSignature==null)
+ return CharOperation.NO_CHAR;
+ int paren = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
+ if (paren == -1) {
+ // could not be determined
+ return CharOperation.NO_CHAR;
+ }
+ // there could be thrown exceptions behind, thus scan one type exactly
+ int last = Util.scanTypeSignature(methodSignature, paren+1);
+ return CharOperation.subarray(methodSignature, paren + 1, last+1);
+}
+/**
+ * Extracts the return type from the given method signature. The method signature is
+ * expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the type signature of the return type
+ * @exception IllegalArgumentException if the signature is syntactically
+ * incorrect
+ */
+public static String getReturnType(String methodSignature) throws IllegalArgumentException {
+ return new String(getReturnType(methodSignature.toCharArray()));
+}
+/**
+ * Returns package fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * + * For example: + *
+ *
+ * getSignatureQualifier({'L', 'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'M', 'a', 'p', '$', 'E', 'n', 't', 'r', 'y', ';'}) -> {'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l'}
+ *
+ *
+ *
+ *
+ * @param typeSignature the type signature
+ * @return the package fragment (separators are '.')
+ *
+ */
+public static char[] getSignatureQualifier(char[] typeSignature) {
+ if(typeSignature == null) return CharOperation.NO_CHAR;
+
+ char[] qualifiedType = Signature.toCharArray(typeSignature);
+
+ int dotCount = 0;
+ indexFound: for(int i = 0; i < typeSignature.length; i++) {
+ switch(typeSignature[i]) {
+ case C_DOT:
+ dotCount++;
+ break;
+ case C_DOLLAR:
+ break indexFound;
+ }
+ }
+
+ if(dotCount > 0) {
+ for(int i = 0; i < qualifiedType.length; i++) {
+ if(qualifiedType[i] == '.') {
+ dotCount--;
+ }
+ if(dotCount <= 0) {
+ return CharOperation.subarray(qualifiedType, 0, i);
+ }
+ }
+ }
+ return CharOperation.NO_CHAR;
+}
+/**
+ * Returns package fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * + * For example: + *
+ *
+ * getSignatureQualifier("Ljava.util.Map$Entry") -> "java.util"
+ *
+ *
+ *
+ *
+ * @param typeSignature the type signature
+ * @return the package fragment (separators are '.')
+ *
+ */
+public static String getSignatureQualifier(String typeSignature) {
+ return new String(getSignatureQualifier(typeSignature == null ? null : typeSignature.toCharArray()));
+}
+/**
+ * Returns type fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * + * For example: + *
+ *
+ * getSignatureSimpleName({'L', 'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'M', 'a', 'p', '$', 'E', 'n', 't', 'r', 'y', ';'}) -> {'M', 'a', 'p', '.', 'E', 'n', 't', 'r', 'y'}
+ *
+ *
+ *
+ *
+ * @param typeSignature the type signature
+ * @return the type fragment (separators are '.')
+ *
+ */
+public static char[] getSignatureSimpleName(char[] typeSignature) {
+ if(typeSignature == null) return CharOperation.NO_CHAR;
+
+ char[] qualifiedType = Signature.toCharArray(typeSignature);
+
+// int dotCount = 0;
+// indexFound: for(int i = 0; i < typeSignature.length; i++) {
+// switch(typeSignature[i]) {
+// case C_DOT:
+// dotCount++;
+// break;
+// case C_GENERIC_START:
+// break indexFound;
+// case C_DOLLAR:
+// break indexFound;
+// }
+// }
+//
+// if(dotCount > 0) {
+// for(int i = 0; i < qualifiedType.length; i++) {
+// if(qualifiedType[i] == '.') {
+// dotCount--;
+// }
+// if(dotCount <= 0) {
+// return CharOperation.subarray(qualifiedType, i + 1, qualifiedType.length);
+// }
+// }
+// }
+ return qualifiedType;
+}
+/**
+ * Returns type fragment of a type signature. The package fragment separator must be '.'
+ * and the type fragment separator must be '$'.
+ * + * For example: + *
+ *
+ * getSignatureSimpleName("Ljava.util.Map$Entry") -> "Map.Entry"
+ *
+ *
+ *
+ *
+ * @param typeSignature the type signature
+ * @return the type fragment (separators are '.')
+ *
+ */
+public static String getSignatureSimpleName(String typeSignature) {
+ return new String(getSignatureSimpleName(typeSignature == null ? null : typeSignature.toCharArray()));
+}
+
+/**
+ * Returns the last segment of the given dot-separated qualified name.
+ * Returns the given name if it is not qualified.
+ * + * For example: + *
+ *
+ * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ *
+ *
+ *
+ *
+ * @param name the name
+ * @return the last segment of the qualified name
+ * @exception NullPointerException if name is null
+ *
+ */
+public static char[] getSimpleName(char[] name) {
+
+ int lastDot = -1;
+ int depth = 0;
+ int length = name.length;
+ lastDotLookup: for (int i = length -1; i >= 0; i--) {
+ switch (name[i]) {
+ case '.':
+ if (depth == 0) {
+ lastDot = i;
+ break lastDotLookup;
+ }
+ break;
+ }
+ }
+
+ if (lastDot < 0) {
+ return name;
+ }
+ return CharOperation.subarray(name, lastDot + 1, length);
+}
+/**
+ * Returns the last segment of the given dot-separated qualified name.
+ * Returns the given name if it is not qualified.
+ * + * For example: + *
+ *+ * + * + * @param name the name + * @return the last segment of the qualified name + * @exception NullPointerException if name is null + */ +public static String getSimpleName(String name) { + int lastDot = -1; + int depth = 0; + int length = name.length(); + lastDotLookup: for (int i = length -1; i >= 0; i--) { + switch (name.charAt(i)) { + case '.': + if (depth == 0) { + lastDot = i; + break lastDotLookup; + } + break; + } + } + if (lastDot < 0) { + return name; + } + return name.substring(lastDot + 1, length); +} + +/** + * Returns all segments of the given dot-separated qualified name. + * Returns an array with only the given name if it is not qualified. + * Returns an empty array if the name is empty. + *+ * getSimpleName("java.lang.Object") -> "Object" + *
+ *+ * getSimpleName("java.util.Map<java.lang.String, java.lang.Object>") -> "Map<String,Object>" + *
+ *
+ * For example: + *
+ *
+ * getSimpleNames({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}
+ * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
+ * getSimpleNames({}) -> {}
+ * getSimpleNames({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g'}}
+ *
+ *
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * @exception NullPointerException if name is null
+ *
+ */
+public static char[][] getSimpleNames(char[] name) {
+ int length = name == null ? 0 : name.length;
+ if (length == 0)
+ return CharOperation.NO_CHAR_CHAR;
+
+ int wordCount = 1;
+ for (int i = 0; i < length; i++)
+ switch(name[i]) {
+ case C_DOT:
+ wordCount++;
+ break;
+ }
+ char[][] split = new char[wordCount][];
+ int last = 0, currentWord = 0;
+ for (int i = 0; i < length; i++) {
+ if (name[i] == C_DOT) {
+ split[currentWord] = new char[i - last];
+ System.arraycopy(
+ name,
+ last,
+ split[currentWord++],
+ 0,
+ i - last);
+ last = i + 1;
+ }
+ }
+ split[currentWord] = new char[length - last];
+ System.arraycopy(name, last, split[currentWord], 0, length - last);
+ return split;
+}
+/**
+ * Returns all segments of the given dot-separated qualified name.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ * + * For example: + *
+ *
+ * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
+ * getSimpleNames("Object") -> {"Object"}
+ * getSimpleNames("") -> {}
+ * getSimpleNames("java.util.List<java.lang.String>") ->
+ * {"java", "util", "List<java.lang.String>"}
+ *
+ *
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * @exception NullPointerException if name is null
+ */
+public static String[] getSimpleNames(String name) {
+ return CharOperation.toStrings(getSimpleNames(name.toCharArray()));
+}
+
+/**
+ * Converts the given method signature to a readable form. The method signature is expected to
+ * be dot-based.
+ * + * For example: + *
+ *
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ *
+ *
+ *
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @return the char array representation of the method signature
+ *
+ *
+ */
+public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+ return toCharArray(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
+}
+/**
+ * Converts the given method signature to a readable form. The method signature is expected to
+ * be dot-based.
+ * + * For example: + *
+ *
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ *
+ *
+ *
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @param isVargArgs true
if the last argument should be displayed as a
+ * variable argument, false
otherwise.
+ * @return the char array representation of the method signature
+ *
+ *
+ */
+public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVargArgs) {
+ int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
+ if (firstParen == -1) {
+ throw new IllegalArgumentException();
+ }
+
+ StringBuffer buffer = new StringBuffer(methodSignature.length + 10);
+
+ // return type
+ if (includeReturnType) {
+ char[] rts = getReturnType(methodSignature);
+ appendTypeSignature(rts, 0 , fullyQualifyTypeNames, buffer);
+ buffer.append(' ');
+ }
+
+ // selector
+ if (methodName != null) {
+ buffer.append(methodName);
+ }
+
+ // parameters
+ buffer.append('(');
+ char[][] pts = getParameterTypes(methodSignature);
+ for (int i = 0, max = pts.length; i < max; i++) {
+ if (i == max - 1) {
+ appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer, isVargArgs);
+ } else {
+ appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer);
+ }
+ if (parameterNames != null) {
+ buffer.append(' ');
+ buffer.append(parameterNames[i]);
+ }
+ if (i != pts.length - 1) {
+ buffer.append(',');
+ buffer.append(' ');
+ }
+ }
+ buffer.append(')');
+ char[] result = new char[buffer.length()];
+ buffer.getChars(0, buffer.length(), result, 0);
+ return result;
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ *
+ * + * For example: + *
+ *
+ * toString({'[', 'L', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', ';'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '[', ']'}
+ * toString({'I'}) -> {'i', 'n', 't'}
+ * toString({'+', 'L', 'O', 'b', 'j', 'e', 'c', 't', ';'}) -> {'?', ' ', 'e', 'x', 't', 'e', 'n', 'd', 's', ' ', 'O', 'b', 'j', 'e', 'c', 't'}
+ *
+ *
+ *
+ *
+ * Note: This method assumes that a type signature containing a '$'
+ * is an inner type signature. While this is correct in most cases, someone could
+ * define a non-inner type name containing a '$'
. Handling this
+ * correctly in all cases would have required resolving the signature, which
+ * generally not feasible.
+ *
true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature
+ * @see Util#scanTypeSignature(char[], int)
+ */
+private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
+}
+/**
+ * Scans the given string for a type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @param isVarArgs true
if the type must be displayed as a
+ * variable argument, false
otherwise. In this case, the type must be an array type
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature, or if isVarArgs is true
,
+ * and the type is not an array type signature.
+ * @see Util#scanTypeSignature(char[], int)
+ */
+private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer, boolean isVarArgs) {
+ // need a minimum 1 char
+ if (start >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (isVarArgs) {
+ switch (c) {
+ case C_ARRAY :
+ return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, true);
+ case C_RESOLVED :
+ case C_UNRESOLVED :
+ case C_VOID :
+ default:
+ throw new IllegalArgumentException(); // a var args is an array type
+ }
+ } else {
+ switch (c) {
+ case C_ARRAY :
+ return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+ case C_RESOLVED :
+ case C_UNRESOLVED :
+ return appendClassTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+ case C_COMPILATION_UNIT :
+ return appendCompilationUnitSignature(string, start, fullyQualifyTypeNames, buffer);
+ case C_ANY :
+ buffer.append(ANY);
+ return start;
+ case C_VOID :
+ buffer.append(VOID);
+ return start;
+ default :
+ /* either the string is not formated as a signature, or we do not know
+ * how to handle it, so just return it, this is preferable to throwing
+ * an unnecessary exception
+ */
+ buffer.append(string);
+ return start;
+ }
+ }
+}
+
+
+private static int appendCompilationUnitSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ // need a minimum 3 chars "Lx;"
+ if (start >= string.length - 2) {
+ throw new IllegalArgumentException();
+ }
+ // must start in "L" or "Q"
+ char c = string[start];
+ if (c != C_COMPILATION_UNIT) {
+ throw new IllegalArgumentException();
+ }
+ int p = start + 1;
+ while (true) {
+ if (p >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ c = string[p];
+ switch(c) {
+ case C_SEMICOLON :
+ // all done
+ return p;
+ default :
+ buffer.append(c);
+ }
+ p++;
+ }
+}
+
+
+
+/**
+ * Scans the given string for an array type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an array type signature
+ * @see Util#scanArrayTypeSignature(char[], int)
+ */
+private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
+}
+
+/**
+ * Scans the given string for an array type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param isVarArgs true
if the array type must be displayed as a
+ * variable argument, false
otherwise
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an array type signature
+ * @see Util#scanArrayTypeSignature(char[], int)
+ */
+private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer, boolean isVarArgs) {
+ int length = string.length;
+ // need a minimum 2 char
+ if (start >= length - 1) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (c != C_ARRAY) {
+ throw new IllegalArgumentException();
+ }
+
+ int index = start;
+ c = string[++index];
+ while(c == C_ARRAY) {
+ // need a minimum 2 char
+ if (index >= length - 1) {
+ throw new IllegalArgumentException();
+ }
+ c = string[++index];
+ }
+
+ int e = appendTypeSignature(string, index, fullyQualifyTypeNames, buffer);
+
+ for(int i = 1, dims = index - start; i < dims; i++) {
+ buffer.append('[').append(']');
+ }
+
+ if (isVarArgs) {
+ buffer.append('.').append('.').append('.');
+ } else {
+ buffer.append('[').append(']');
+ }
+ return e;
+}
+/**
+ * Scans the given string for a class type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a class type signature
+ * @see Util#scanClassTypeSignature(char[], int)
+ */
+private static int appendClassTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ // need a minimum 3 chars "Lx;"
+ if (start >= string.length - 2) {
+ throw new IllegalArgumentException();
+ }
+ // must start in "L" or "Q"
+ char c = string[start];
+ if (c != C_RESOLVED && c != C_UNRESOLVED) {
+ throw new IllegalArgumentException();
+ }
+ boolean resolved = (c == C_RESOLVED);
+ boolean removePackageQualifiers = !fullyQualifyTypeNames;
+ if (!resolved) {
+ // keep everything in an unresolved name
+ removePackageQualifiers = false;
+ }
+ int p = start + 1;
+ int checkpoint = buffer.length();
+ int innerTypeStart = -1;
+ boolean inAnonymousType = false;
+ while (true) {
+ if (p >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ c = string[p];
+ switch(c) {
+ case C_SEMICOLON :
+ // all done
+ return p;
+ case C_DOT :
+ if (removePackageQualifiers) {
+ // erase package prefix
+ buffer.setLength(checkpoint);
+ } else {
+ buffer.append('.');
+ }
+ break;
+ case '/' :
+ if (removePackageQualifiers) {
+ // erase package prefix
+ buffer.setLength(checkpoint);
+ } else {
+ buffer.append('/');
+ }
+ break;
+ default :
+ if (innerTypeStart != -1 && !inAnonymousType && Character.isDigit(c)) {
+ inAnonymousType = true;
+ buffer.setLength(innerTypeStart); // remove '.'
+ buffer.insert(checkpoint, "new "); //$NON-NLS-1$
+ buffer.append("(){}"); //$NON-NLS-1$
+ }
+ if (!inAnonymousType)
+ buffer.append(c);
+ innerTypeStart = -1;
+ }
+ p++;
+ }
+}
+
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ * + * For example: + *
+ *
+ * toQualifiedName({{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{}}) -> {}
+ *
+ *
+ *
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ *
+ *
+ */
+public static char[] toQualifiedName(char[][] segments) {
+ int length = segments.length;
+ if (length == 0) return CharOperation.NO_CHAR;
+ if (length == 1) return segments[0];
+
+ int resultLength = 0;
+ for (int i = 0; i < length; i++) {
+ resultLength += segments[i].length+1;
+ }
+ resultLength--;
+ char[] result = new char[resultLength];
+ int index = 0;
+ for (int i = 0; i < length; i++) {
+ char[] segment = segments[i];
+ int segmentLength = segment.length;
+ System.arraycopy(segment, 0, result, index, segmentLength);
+ index += segmentLength;
+ if (i != length-1) {
+ result[index++] = C_DOT;
+ }
+ }
+ return result;
+}
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ * + * For example: + *
+ *
+ * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
+ * toQualifiedName(new String[] {"Object"}) -> "Object"
+ * toQualifiedName(new String[0]) -> ""
+ *
+ *
+ *
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ */
+public static String toQualifiedName(String[] segments) {
+ int length = segments.length;
+ char[][] charArrays = new char[length][];
+ for (int i = 0; i < length; i++) {
+ charArrays[i] = segments[i].toCharArray();
+ }
+ return new String(toQualifiedName(charArrays));
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ *
+ * + * For example: + *
+ *
+ * toString("[Ljava.lang.String;") -> "java.lang.String[]"
+ * toString("I") -> "int"
+ * toString("+QObject;") -> "? extends Object"
+ *
+ *
+ *
+ *
+ * Note: This method assumes that a type signature containing a '$'
+ * is an inner type signature. While this is correct in most cases, someone could
+ * define a non-inner type name containing a '$'
. Handling this
+ * correctly in all cases would have required resolving the signature, which
+ * generally not feasible.
+ *
null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @see #toCharArray(char[], char[], char[][], boolean, boolean)
+ * @return the string representation of the method signature
+ */
+public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+ return toString(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
+}
+/**
+ * Converts the given method signature to a readable string. The method signature is expected to
+ * be dot-based.
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @param isVarArgs true
if the last argument should be displayed as a
+ * variable argument, false
otherwise
+ * @see #toCharArray(char[], char[], char[][], boolean, boolean)
+ * @return the string representation of the method signature
+ *
+ *
+ */
+public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVarArgs) {
+ char[][] params;
+ if (parameterNames == null) {
+ params = null;
+ } else {
+ int paramLength = parameterNames.length;
+ params = new char[paramLength][];
+ for (int i = 0; i < paramLength; i++) {
+ params[i] = parameterNames[i].toCharArray();
+ }
+ }
+ return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType, isVarArgs));
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ToolFactory.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ToolFactory.java
new file mode 100644
index 0000000..0722426
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ToolFactory.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.compiler.IScanner;
+import org.eclipse.wst.jsdt.core.formatter.CodeFormatter;
+import org.eclipse.wst.jsdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.core.util.PublicScanner;
+import org.eclipse.wst.jsdt.internal.formatter.DefaultCodeFormatter;
+
+/**
+ * Factory for creating various compiler tools, such as scanners, parsers and compilers.
+ * + * This class provides static methods only; it is not intended to be instantiated or subclassed by clients. + *
+ * + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class ToolFactory { + + /** + * This mode is used for formatting new code when some formatter options should not be used. + * In particular, options that preserve the indentation of comments are not used. + * In the future, newly added options may be ignored as well. + *Clients that are formatting new code are recommended to use this mode. + *
+ * + * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN + * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN + * @see #createCodeFormatter(Map, int) + */ + public static final int M_FORMAT_NEW = new Integer(0).intValue(); + + /** + * This mode is used for formatting existing code when all formatter options should be used. + * In particular, options that preserve the indentation of comments are used. + *Clients that are formatting existing code are recommended to use this mode. + *
+ * + * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN + * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN + * @see #createCodeFormatter(Map, int) + */ + public static final int M_FORMAT_EXISTING = new Integer(1).intValue(); + + /** + * Create an instance of the built-in code formatter. + *The given options should at least provide the source level ({@link JavaScriptCore#COMPILER_SOURCE}), + * the compiler compliance level ({@link JavaScriptCore#COMPILER_COMPLIANCE}) and the target platform + * ({@link JavaScriptCore#COMPILER_CODEGEN_TARGET_PLATFORM}). + * Without these options, it is not possible for the code formatter to know what kind of source it needs to format. + *
+ * Note this is equivalent to createCodeFormatter(options, M_FORMAT_NEW)
. Thus some code formatter options
+ * may be ignored. See @{link {@link #M_FORMAT_NEW} for more details.
+ *
JavaScriptCore#getDefaultOptions()
. If set to null
, then use
+ * the current settings from JavaScriptCore#getOptions
.
+ * @return an instance of the built-in code formatter
+ * @see CodeFormatter
+ * @see JavaScriptCore#getOptions()
+ */
+ public static CodeFormatter createCodeFormatter(Map options){
+ return createCodeFormatter(options, M_FORMAT_NEW);
+ }
+
+ /**
+ * Create an instance of the built-in code formatter.
+ * The given options should at least provide the source level ({@link JavaScriptCore#COMPILER_SOURCE}), + * the compiler compliance level ({@link JavaScriptCore#COMPILER_COMPLIANCE}) and the target platform + * ({@link JavaScriptCore#COMPILER_CODEGEN_TARGET_PLATFORM}). + * Without these options, it is not possible for the code formatter to know what kind of source it needs to format. + *
+ *The given mode determines what options should be enabled when formatting the code. It can have the following + * values: {@link #M_FORMAT_NEW}, {@link #M_FORMAT_EXISTING}, but other values may be added in the future. + *
+ * + * @param options the options map to use for formatting with the default code formatter. Recognized options + * are documented onJavaScriptCore#getDefaultOptions()
. If set to null
, then use
+ * the current settings from JavaScriptCore#getOptions
.
+ * @param mode the given mode to modify the given options.
+ *
+ * @return an instance of the built-in code formatter
+ * @see CodeFormatter
+ * @see JavaScriptCore#getOptions()
+ */
+ public static CodeFormatter createCodeFormatter(Map options, int mode) {
+ if (options == null) options = JavaScriptCore.getOptions();
+ Map currentOptions = new HashMap(options);
+ if (mode == M_FORMAT_NEW) {
+ // disable the option for not indenting comments starting on first column
+ currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.FALSE);
+ currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.FALSE);
+ }
+ return new DefaultCodeFormatter(currentOptions);
+ }
+
+
+
+
+
+ /**
+ * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+ * used to tokenize some source in a JavaScript aware way.
+ * Here is a typical scanning loop:
+ *
+ *
+ *
+ * IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+ * scanner.setSource("int i = 0;".toCharArray());
+ * while (true) {
+ * int token = scanner.getNextToken();
+ * if (token == ITerminalSymbols.TokenNameEOF) break;
+ * System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+ * }
+ *
+ *
+ *
+ *
+ * The returned scanner will tolerate unterminated line comments (missing line separator). It can be made stricter
+ * by using API with extra boolean parameter (strictCommentMode
).
+ *
+ * @param tokenizeComments if set to false
, comments will be silently consumed
+ * @param tokenizeWhiteSpace if set to false
, white spaces will be silently consumed,
+ * @param assertMode if set to false
, occurrences of 'assert' will be reported as identifiers
+ * (ITerminalSymbols#TokenNameIdentifier
), whereas if set to true
, it
+ * would report assert keywords (ITerminalSymbols#TokenNameassert
).
+ * @param recordLineSeparator if set to true
, the scanner will record positions of encountered line
+ * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+ * can then be extracted using IScanner#getLineEnds
. Only non-unicode escape sequences are
+ * considered as valid line separators.
+ * @return a scanner
+ * @see org.eclipse.wst.jsdt.core.compiler.IScanner
+ */
+ public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean assertMode, boolean recordLineSeparator){
+
+ PublicScanner scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/, assertMode ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+ scanner.recordLineSeparator = recordLineSeparator;
+ return scanner;
+ }
+
+ /**
+ * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+ * used to tokenize some source in a JavaScript aware way.
+ * Here is a typical scanning loop:
+ *
+ *
+ *
+ *
+ *
+ * IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+ * scanner.setSource("int i = 0;".toCharArray());
+ * while (true) {
+ * int token = scanner.getNextToken();
+ * if (token == ITerminalSymbols.TokenNameEOF) break;
+ * System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+ * }
+ *
+ *
+ * The returned scanner will tolerate unterminated line comments (missing line separator). It can be made stricter
+ * by using API with extra boolean parameter (strictCommentMode
).
+ *
+ * @param tokenizeComments if set to false
, comments will be silently consumed
+ * @param tokenizeWhiteSpace if set to false
, white spaces will be silently consumed,
+ * @param recordLineSeparator if set to true
, the scanner will record positions of encountered line
+ * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+ * can then be extracted using IScanner#getLineEnds
. Only non-unicode escape sequences are
+ * considered as valid line separators.
+ * @param sourceLevel if set to "1.3"
or null
, occurrences of 'assert' will be reported as identifiers
+ * (ITerminalSymbols#TokenNameIdentifier
), whereas if set to "1.4"
, it
+ * would report assert keywords (ITerminalSymbols#TokenNameassert
).
+ * @return a scanner
+ * @see org.eclipse.wst.jsdt.core.compiler.IScanner
+ */
+ public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel) {
+ PublicScanner scanner = null;
+ long level = CompilerOptions.versionToJdkLevel(sourceLevel);
+ if (level == 0) level = ClassFileConstants.JDK1_3; // fault-tolerance
+ scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,level /*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+ scanner.recordLineSeparator = recordLineSeparator;
+ return scanner;
+ }
+
+ /**
+ * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+ * used to tokenize some source in a JavaScript aware way.
+ * Here is a typical scanning loop:
+ *
+ *
+ *
+ *
+ *
+ * IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+ * scanner.setSource("int i = 0;".toCharArray());
+ * while (true) {
+ * int token = scanner.getNextToken();
+ * if (token == ITerminalSymbols.TokenNameEOF) break;
+ * System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+ * }
+ *
+ *
+ * The returned scanner will tolerate unterminated line comments (missing line separator). It can be made stricter
+ * by using API with extra boolean parameter (strictCommentMode
).
+ *
+ * @param tokenizeComments if set to false
, comments will be silently consumed
+ * @param tokenizeWhiteSpace if set to false
, white spaces will be silently consumed,
+ * @param recordLineSeparator if set to true
, the scanner will record positions of encountered line
+ * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+ * can then be extracted using IScanner#getLineEnds
. Only non-unicode escape sequences are
+ * considered as valid line separators.
+ * @param sourceLevel if set to "1.3"
or null
, occurrences of 'assert' will be reported as identifiers
+ * (ITerminalSymbols#TokenNameIdentifier
), whereas if set to "1.4"
, it
+ * would report assert keywords (ITerminalSymbols#TokenNameassert
).
+ * @param complianceLevel This is used to support the Unicode 4.0 character sets. if set to 1.5 or above,
+ * the Unicode 4.0 is supporte, otherwise Unicode 3.0 is supported.
+ * @return a scanner
+ * @see org.eclipse.wst.jsdt.core.compiler.IScanner
+ *
+ */
+ public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel, String complianceLevel) {
+ PublicScanner scanner = null;
+ long sourceLevelValue = CompilerOptions.versionToJdkLevel(sourceLevel);
+ if (sourceLevelValue == 0) sourceLevelValue = ClassFileConstants.JDK1_3; // fault-tolerance
+ long complianceLevelValue = CompilerOptions.versionToJdkLevel(complianceLevel);
+ if (complianceLevelValue == 0) complianceLevelValue = ClassFileConstants.JDK1_3; // fault-tolerance
+ scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,sourceLevelValue /*sourceLevel*/, complianceLevelValue, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+ scanner.recordLineSeparator = recordLineSeparator;
+ return scanner;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/UnimplementedException.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/UnimplementedException.java
new file mode 100644
index 0000000..e56246d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/UnimplementedException.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+public class UnimplementedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public UnimplementedException() {
+ super();
+ }
+
+ public UnimplementedException(String arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/WorkingCopyOwner.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/WorkingCopyOwner.java
new file mode 100644
index 0000000..c1c6202
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/WorkingCopyOwner.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.jsdt.internal.core.BufferManager;
+import org.eclipse.wst.jsdt.internal.core.CompilationUnit;
+import org.eclipse.wst.jsdt.internal.core.DefaultWorkingCopyOwner;
+import org.eclipse.wst.jsdt.internal.core.ExternalJavaProject;
+import org.eclipse.wst.jsdt.internal.core.PackageFragment;
+
+/**
+ * The owner of an {@link IJavaScriptUnit} handle in working copy mode.
+ * An owner is used to identify a working copy and to create its buffer.
+ *
+ * Clients should subclass this class to instantiate a working copy owner that is specific to their need and that + * they can pass in to various APIs (e.g. {@link IType#resolveType(String, WorkingCopyOwner)}. + * Clients can also override the default implementation of {@link #createBuffer(IJavaScriptUnit)}. + *
+ * Note: even though this class has no abstract method, which means that it provides functional default behavior, + * it is still an abstract class, as clients are intended to own their owner implementation. + *
+ * @see IJavaScriptUnit#becomeWorkingCopy(org.eclipse.core.runtime.IProgressMonitor) + * @see IJavaScriptUnit#discardWorkingCopy() + * @see IJavaScriptUnit#getWorkingCopy(org.eclipse.core.runtime.IProgressMonitor) + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public abstract class WorkingCopyOwner { + + /** + * Sets the buffer provider of the primary working copy owner. Note that even if the + * buffer provider is a working copy owner, only itscreateBuffer(IJavaScriptUnit)
+ * method is used by the primary working copy owner. It doesn't replace the internal primary
+ * working owner.
+ * + * This method is for internal use by the jsdt-related plug-ins. + * Clients outside of the jsdt should not reference this method. + *
+ * + * @param primaryBufferProvider the primary buffer provider + */ + public static void setPrimaryBufferProvider(WorkingCopyOwner primaryBufferProvider) { + DefaultWorkingCopyOwner.PRIMARY.primaryBufferProvider = primaryBufferProvider; + } + + /** + * Creates a buffer for the given working copy. + * The new buffer will be initialized with the contents of the underlying file + * if and only if it was not already initialized by the compilation owner (a buffer is + * uninitialized if its content isnull
).
+ * + * Note: This buffer will be associated to the working copy for its entire life-cycle. Another + * working copy on same unit but owned by a different owner would not share the same buffer + * unless its owner decided to implement such a sharing behaviour. + *
+ * + * @param workingCopy the working copy of the buffer + * @return IBuffer the created buffer for the given working copy + * @see IBuffer + */ + public IBuffer createBuffer(IJavaScriptUnit workingCopy) { + + return BufferManager.createBuffer(workingCopy); + } + + /** + * Returns the problem requestor used by a working copy of this working copy owner. + *+ * By default, no problem requestor is configured. Clients can override this + * method to provide a requestor. + *
+ * + * @param workingCopy The problem requestor used for the given working copy. + * @return the problem requestor to be used by working copies of this working + * copy owner ornull
if no problem requestor is configured.
+ *
+ */
+ public IProblemRequestor getProblemRequestor(IJavaScriptUnit workingCopy) {
+ return null;
+ }
+
+ /**
+ * Returns a new working copy with the given name using this working copy owner to
+ * create its buffer.
+ * + * This working copy always belongs to the default package in a package + * fragment root that corresponds to its JavaScript project, and this JavaScript project never exists. + * However this JavaScript project has the given includepath that is used when resolving names + * in this working copy. + *
+ * If a DOM AST is created using this working copy, then given includepath will be used
+ * if bindings need to be resolved. Problems will be reported to the problem requestor
+ * of the current working copy owner problem if it is not null
.
+ *
+ * When the working copy instance is created, an {@link IJavaScriptElementDelta#ADDED added delta} is + * reported on this working copy. + *
+ * Once done with the working copy, users of this method must discard it using + * {@link IJavaScriptUnit#discardWorkingCopy()}. + *
+ * Note that when such working copy is committed, only its buffer is saved (see + * {@link IBuffer#save(IProgressMonitor, boolean)}) but no resource is created. + *
+ * This method is not intended to be overriden by clients. + *
+ * + * @param name the name of the working copy (e.g. "X.js") + * @param classpath the includepath used to resolve names in this working copy + * @param monitor a progress monitor used to report progress while opening the working copy + * ornull
if no progress should be reported
+ * @throws JavaScriptModelException if the contents of this working copy can
+ * not be determined.
+ * @return a new working copy
+ * @see IJavaScriptUnit#becomeWorkingCopy(IProgressMonitor)
+ *
+ */
+ public final IJavaScriptUnit newWorkingCopy(String name, IIncludePathEntry[] classpath, IProgressMonitor monitor) throws JavaScriptModelException {
+ ExternalJavaProject project = new ExternalJavaProject(classpath);
+ IPackageFragment parent = project.getPackageFragmentRoot(Path.EMPTY).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ CompilationUnit result = new CompilationUnit((PackageFragment) parent, name, this);
+ result.becomeWorkingCopy(getProblemRequestor(result), monitor);
+ return result;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ASTVisitor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ASTVisitor.java
new file mode 100644
index 0000000..4a808bf
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ASTVisitor.java
@@ -0,0 +1,563 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.ast;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.infer.InferredAttribute;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+
+
+/**
+ *
+ * A visitor for iterating through the AST Node tree.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class ASTVisitor {
+
+
+ public void acceptProblem(IProblem problem) {
+ // do nothing by default
+ }
+ public void endVisit( IAllocationExpression allocationExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IAND_AND_Expression and_and_Expression) {
+ // do nothing by default
+ }
+ public void endVisit(IArgument argument) {
+ // do nothing by default
+ }
+
+ public void endVisit( IArrayAllocationExpression arrayAllocationExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IArrayInitializer arrayInitializer) {
+ // do nothing by default
+ }
+ public void endVisit(IArrayQualifiedTypeReference arrayQualifiedTypeReference) {
+ // do nothing by default
+ }
+ public void endVisit(IArrayReference arrayReference) {
+ // do nothing by default
+ }
+ public void endVisit(IArrayTypeReference arrayTypeReference) {
+ // do nothing by default
+ }
+ public void endVisit(IAssignment assignment) {
+ // do nothing by default
+ }
+ public void endVisit(IBinaryExpression binaryExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IBlock block) {
+ // do nothing by default
+ }
+ public void endVisit(IBreakStatement breakStatement) {
+ // do nothing by default
+ }
+ public void endVisit(ICaseStatement caseStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IScriptFileDeclaration scriptFileDeclaration) {
+ // do nothing by default
+ }
+ public void endVisit(ICompoundAssignment compoundAssignment) {
+ // do nothing by default
+ }
+ public void endVisit(IConditionalExpression conditionalExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IConstructorDeclaration constructorDeclaration) {
+ // do nothing by default
+ }
+ public void endVisit(IContinueStatement continueStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IDoStatement doStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IDoubleLiteral doubleLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(IEmptyStatement emptyStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IEqualExpression equalExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IExplicitConstructorCall explicitConstructor) {
+ // do nothing by default
+ }
+ public void endVisit(IExtendedStringLiteral extendedStringLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(IFalseLiteral falseLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(IFieldDeclaration fieldDeclaration) {
+ // do nothing by default
+ }
+
+ public void endVisit(IFieldReference fieldDeclaration) {
+ // do nothing by default
+ }
+
+ public void endVisit(IForeachStatement forStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IForStatement forStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IForInStatement forInStatement) {
+ // do nothing by default
+ }
+
+ public void endVisit(IFunctionExpression functionExpression) {
+ }
+
+ public void endVisit(IIfStatement ifStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IImportReference importRef) {
+ // do nothing by default
+ }
+ public void endVisit(InferredType inferredType) {
+ // do nothing by default
+ }
+
+ public void endVisit(IInitializer initializer) {
+ // do nothing by default
+ }
+ public void endVisit(IInstanceOfExpression instanceOfExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IIntLiteral intLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDoc javadoc) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocAllocationExpression expression) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocArgumentExpression expression) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocArrayQualifiedTypeReference typeRef) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocArraySingleTypeReference typeRef) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocFieldReference fieldRef) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocImplicitTypeReference implicitTypeReference) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocMessageSend messageSend) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocQualifiedTypeReference typeRef) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocReturnStatement statement) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocSingleNameReference argument) {
+ // do nothing by default
+ }
+ public void endVisit(IJsDocSingleTypeReference typeRef) {
+ // do nothing by default
+ }
+ public void endVisit(ILabeledStatement labeledStatement) {
+ // do nothing by default
+ }
+ public void endVisit(ILocalDeclaration localDeclaration) {
+ // do nothing by default
+ }
+ public void endVisit(IListExpression listDeclaration) {
+ // do nothing by default
+ }
+ public void endVisit(IFunctionCall messageSend) {
+ // do nothing by default
+ }
+ public void endVisit(IFunctionDeclaration methodDeclaration) {
+ // do nothing by default
+ }
+ public void endVisit(IStringLiteralConcatenation literal) {
+ // do nothing by default
+ }
+ public void endVisit(INullLiteral nullLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(IOR_OR_Expression or_or_Expression) {
+ // do nothing by default
+ }
+ public void endVisit(IPostfixExpression postfixExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IPrefixExpression prefixExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IQualifiedAllocationExpression qualifiedAllocationExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IQualifiedNameReference qualifiedNameReference) {
+ // do nothing by default
+ }
+ public void endVisit(IQualifiedThisReference qualifiedThisReference) {
+ // do nothing by default
+ }
+ public void endVisit(IQualifiedTypeReference qualifiedTypeReference) {
+ // do nothing by default
+ }
+
+ public void endVisit(IRegExLiteral stringLiteral) {
+ // do nothing by default
+ }
+
+
+ public void endVisit(IReturnStatement returnStatement) {
+ // do nothing by default
+ }
+ public void endVisit(ISingleNameReference singleNameReference) {
+ // do nothing by default
+ }
+
+ public void endVisit(ISingleTypeReference singleTypeReference) {
+ // do nothing by default
+ }
+ public void endVisit(IStringLiteral stringLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(ISuperReference superReference) {
+ // do nothing by default
+ }
+ public void endVisit(ISwitchStatement switchStatement) {
+ // do nothing by default
+ }
+
+ public void endVisit(IThisReference thisReference) {
+ // do nothing by default
+ }
+ public void endVisit(IThrowStatement throwStatement) {
+ // do nothing by default
+ }
+ public void endVisit(ITrueLiteral trueLiteral) {
+ // do nothing by default
+ }
+ public void endVisit(ITryStatement tryStatement) {
+ // do nothing by default
+ }
+ public void endVisit(ITypeDeclaration memberTypeDeclaration) {
+ // do nothing by default
+ }
+ public void endVisit(IUnaryExpression unaryExpression) {
+ // do nothing by default
+ }
+ public void endVisit(IUndefinedLiteral undefinedLiteral) {
+ // do nothing by default
+ }
+
+ public void endVisit(IWhileStatement whileStatement) {
+ // do nothing by default
+ }
+ public void endVisit(IWithStatement whileStatement) {
+ // do nothing by default
+ }
+ public boolean visit(IAllocationExpression allocationExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IAND_AND_Expression and_and_Expression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IArgument argument) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IArrayAllocationExpression arrayAllocationExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IArrayInitializer arrayInitializer) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IArrayQualifiedTypeReference arrayQualifiedTypeReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IArrayReference arrayReference) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IArrayTypeReference arrayTypeReference) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IAssignment assignment) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IBinaryExpression binaryExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IBlock block) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IBreakStatement breakStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ICaseStatement caseStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IScriptFileDeclaration compilationUnitDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ICompoundAssignment compoundAssignment) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IConditionalExpression conditionalExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IConstructorDeclaration constructorDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IContinueStatement continueStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IDoStatement doStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IDoubleLiteral doubleLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IEmptyStatement emptyStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IEqualExpression equalExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IExplicitConstructorCall explicitConstructor) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IExtendedStringLiteral extendedStringLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IFalseLiteral falseLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IFieldDeclaration fieldDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IFieldReference fieldReference) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IForeachStatement forStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IForInStatement forInStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IForStatement forStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IFunctionExpression functionExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IIfStatement ifStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IImportReference importRef) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(InferredType inferredType) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(InferredMethod inferredMethod) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(InferredAttribute inferredField) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IInitializer initializer) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IInstanceOfExpression instanceOfExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IIntLiteral intLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IJsDoc javadoc) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocAllocationExpression expression) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocArgumentExpression expression) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocArrayQualifiedTypeReference typeRef) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocArraySingleTypeReference typeRef) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocFieldReference fieldRef) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocImplicitTypeReference implicitTypeReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocMessageSend messageSend) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocQualifiedTypeReference typeRef) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocReturnStatement statement) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocSingleNameReference argument) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IJsDocSingleTypeReference typeRef) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(ILabeledStatement labeledStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ILocalDeclaration localDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IListExpression listDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IFunctionCall functionCall) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IFunctionDeclaration functionDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IStringLiteralConcatenation literal) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(INullLiteral nullLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IOR_OR_Expression or_or_Expression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IPostfixExpression postfixExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IPrefixExpression prefixExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IQualifiedAllocationExpression qualifiedAllocationExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IQualifiedNameReference qualifiedNameReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IQualifiedThisReference qualifiedThisReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IQualifiedTypeReference qualifiedTypeReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IRegExLiteral stringLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IReturnStatement returnStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ISingleNameReference singleNameReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(ISingleTypeReference singleTypeReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IStringLiteral stringLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ISuperReference superReference) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ISwitchStatement switchStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IThisReference thisReference) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IThrowStatement throwStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ITrueLiteral trueLiteral) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ITryStatement tryStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ITypeDeclaration localTypeDeclaration) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IUnaryExpression unaryExpression) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IUndefinedLiteral undefined) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IWhileStatement whileStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IWithStatement whileStatement) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(IObjectLiteral literal) {
+ return true; // do nothing by default, keep traversing
+ }
+ public void endVisit(IObjectLiteral literal) {
+ }
+ public boolean visit(IObjectLiteralField field) {
+ return true; // do nothing by default, keep traversing
+ }
+ public void endVisit(IObjectLiteralField field) {
+ }
+
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAND_AND_Expression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAND_AND_Expression.java
new file mode 100644
index 0000000..3b64692
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAND_AND_Expression.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.ast;
+
+
+/**
+ * Representation of a && expression
+ * + * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IAND_AND_Expression extends IBinaryExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IASTNode.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IASTNode.java new file mode 100644 index 0000000..be19c17 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IASTNode.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2005, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * Abstract base class for AST nodes. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IASTNode { + + + //public static final int AST_FUNCTION = 1; + //public static final int AST_ABSTRACT_METHOD_DECLARATION = 0; + public static final int AST_NODE=0; + public static final int ABSTRACT_FUNCTION_DECLARATION=1; + public static final int ABSTRACT_VARIABLE_DECLARATION=2; + public static final int ALLOCATION_EXPRESSION=3; + public static final int AND_AND_EXPRESSION=4; + public static final int ARGUMENT=7; + public static final int ARRAY_ALLOCATION_EXPRESSION=8; + public static final int ARRAY_INITIALIZER=9; + public static final int ARRAY_QUALIFIED_TYPE_REFERENCE=10; + public static final int ARRAY_REFERENCE=11; + public static final int ARRAY_TYPE_REFERENCE=12; + public static final int ASSIGNMENT=14; + public static final int BINARY_EXPRESSION=15; + public static final int BLOCK=16; + public static final int BRANCH_STATEMENT=17; + public static final int BREAK_STATEMENT=18; + public static final int CASE_STATEMENT=19; + public static final int CHAR_LITERAL=21; + public static final int COMBINED_BINARY_EXPRESSION=22; + public static final int COMPOUND_ASSIGNMENT=23; + public static final int CONDITIONAL_EXPRESSION=24; + public static final int CONSTRUCTOR_DECLARATION=25; + public static final int CONTINUE_STATEMENT=26; + public static final int DO_STATEMENT=27; + public static final int DOUBLE_LITERAL=28; + public static final int EMPTY_EXPRESSION=29; + public static final int EMPTY_STATEMENT=30; + public static final int EQUAL_EXPRESSION=31; + public static final int EXPLICIT_CONSTRUCTOR_CALL=32; + public static final int EXPRESSION=33; + public static final int EXTENDED_STRING_LITERAL=34; + public static final int FALSE_LITERAL=35; + public static final int FIELD_DECLARATION=36; + public static final int FIELD_REFERENCE=37; + public static final int FLOAT_LITERAL=38; + public static final int FOR_EACH_STATEMENT=39; + public static final int FOR_IN_STATEMENT=40; + public static final int FOR_STATEMENT=41; + public static final int FUNCTION_CALL=42; + public static final int FUNCTION_DECLARATION=43; + public static final int FUNCTION_EXPRESSION=44; + public static final int IF_STATEMENT=45; + public static final int IMPORT_REFERENCE=46; + public static final int INITIALIZER=47; + public static final int INSTANCEOF_EXPRESSION=48; + public static final int INT_LITERAL=49; + public static final int INT_LITERAL_MIN_VALUE=50; + public static final int JSDOC=51; + public static final int JSDOC_ALLOCATION_EXPRESSION=52; + public static final int JSDOC_ARGUMENTEXPRESSION=53; + public static final int JSDOC_ARRAY_QUALIFIED_TYPE_REFERENCE=54; + public static final int JSDOC_ARRAY_SINGLE_TYPE_REFERENCE=55; + public static final int JSDOC_FIELD_REFERENCE=56; + public static final int JSDOC_IMPLICIT_TYPE_REFERENCE=57; + public static final int JSDOC_MESSAGE_SEND=58; + public static final int JSDOC_QUALIFIED_TYPE_REFERENCE=59; + public static final int JSDOC_RETURN_STATEMENT=60; + public static final int JSDOC_SINGLE_NAME_REFERENCE=61; + public static final int JSDOC_SINGLE_TYPE_REFERENCE=62; + public static final int LABELED_STATEMENT=63; + public static final int LIST_EXPRESSION=64; + public static final int LITERAL=65; + public static final int LOCAL_DECLARATION=66; + public static final int LONG_LITERAL=67; + public static final int LONG_LITERAL_MIN_VALUE=68; + public static final int MAGIC_LITERAL=69; + public static final int NAME_REFERENCE=72; + public static final int NULL_LITERAL=74; + public static final int NUMBER_LITERAL=75; + public static final int OBJECT_LITERAL=76; + public static final int OBJECT_LITERAL_FIELD=77; + public static final int OPERATOR_EXPRESSION=78; + public static final int OR_OR_EXPRESSION=79; + public static final int PARAMETERIZED_QUALIFIED_TYPE_REFERENCE=80; + public static final int PARAMETERIZED_SINGLE_TYPE_REFERENCE=81; + public static final int POSTFIX_EXPRESSION=82; + public static final int PREFIX_EXPRESSION=83; + public static final int PROGRAM_ELEMENT=84; + public static final int QUALIFIED_ALLOCATION_EXPRESSION=85; + public static final int QUALIFIED_NAME_REFERENCE=86; + public static final int QUALIFIED_SUPER_REFERENCE=87; + public static final int QUALIFIED_THIS_REFERENCE=88; + public static final int QUALIFIED_TYPE_REFERENCE=89; + public static final int REFERENCE=90; + public static final int REG_EX_LITERAL=91; + public static final int RETURN_STATEMENT=92; + public static final int SCRIPT_FILE_DECLARATION=93; + public static final int SINGLE_NAME_REFERENCE=95; + public static final int SINGLE_TYPE_REFERENCE=96; + public static final int STATEMENT=97; + public static final int STRING_LITERAL=98; + public static final int STRING_LITERAL_CONCATENATION=99; + public static final int SUB_ROUTINE_STATEMENT=100; + public static final int SUPER_REFERENCE=101; + public static final int SWITCH_STATEMENT=102; + public static final int THIS_REFERENCE=103; + public static final int THROW_STATEMENT=104; + public static final int TRUE_LITERAL=105; + public static final int TRY_STATEMENT=106; + public static final int TYPE_DECLARATION=107; + public static final int TYPE_PARAMETER=108; + public static final int TYPE_REFERENCE=109; + public static final int UNARY_EXPRESSION=110; + public static final int UNDEFINED_LITERAL=111; + public static final int WHILE_STATEMENT=112; + public static final int WITH_STATEMENT=114; + public static final int CLASS_LITERAL_ACCESS=115; + public static final int CL_INIT=116; + public static final int OBJECT_GETTER_SETTER_FIELD=117; + public int sourceStart() ; + public int sourceEnd(); + public int getASTType(); + + public void traverse(ASTVisitor visitor); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAbstractFunctionDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAbstractFunctionDeclaration.java new file mode 100644 index 0000000..eb3cc2a --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAbstractFunctionDeclaration.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.core.infer.InferredMethod; +import org.eclipse.wst.jsdt.core.infer.InferredType; + +/** + * Abstract representation of a Function declaration. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IAbstractFunctionDeclaration extends IStatement{ + + /** + * Set the function arguments + * @param args IArgument[] + */ + public void setArguments( IArgument[] args); + + /** + * Get the function arguments + * @return arguments + */ + public IArgument[] getArguments(); + + /** + * Get the function jsdoc + * @return jsdoc + */ + IJsDoc getJsDoc(); + + /** + * Get the function statements + * @return statements + */ + IProgramElement[] getStatements(); + + /** + * Get the function name + * + * @return name + */ + char[] getName(); + + /** + * Set the inferred return type + * + * @param inferred return type + */ + void setInferredType(InferredType type); + + /** + * Get the inferred return type for the function + * @return inferred type + */ + InferredType getInferredType(); + + /** + * Get the Inferred method associated with this function + * @return + */ + InferredMethod getInferredMethod(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAbstractVariableDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAbstractVariableDeclaration.java new file mode 100644 index 0000000..ddc9b38 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAbstractVariableDeclaration.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.core.infer.InferredType; +/** + * Abstract representation of a var. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IAbstractVariableDeclaration extends IStatement{ + /** + * Set the inferred type of the var + * @param inferred type + */ + public void setInferredType(InferredType type); + /** + * Get the inferred type of the var + * @return inferred type + */ + public InferredType getInferredType(); + /** + * get the var name + * @return name + */ + public char[] getName(); + /** + * Get the initialization expression of the var + * @return initialization expression + */ + public IExpression getInitialization(); + /** + * get the JSDoc for the var + * @return jsdoc + */ + public IJsDoc getJsDoc(); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAllocationExpression.java new file mode 100644 index 0000000..058d59c --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAllocationExpression.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * Representation of a new expression + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IAllocationExpression { + + /** + * The expression being allocated + * @return + */ + IExpression getMember(); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArgument.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArgument.java new file mode 100644 index 0000000..38487b3 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArgument.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope; +import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding; + +/** + * Representation of a function argument + *+ * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IArgument extends ILocalDeclaration{ + + public char[] getComment(); + public abstract void bind(MethodScope scope, TypeBinding typeBinding, boolean used); + public abstract StringBuffer print(int indent, StringBuffer output); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayAllocationExpression.java new file mode 100644 index 0000000..983fd03 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayAllocationExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IArrayAllocationExpression extends IExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayInitializer.java new file mode 100644 index 0000000..92dce68 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayInitializer.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * representation of an array initializer + *+ * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IArrayInitializer extends IExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayQualifiedTypeReference.java new file mode 100644 index 0000000..aa02642 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayQualifiedTypeReference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IArrayQualifiedTypeReference extends IQualifiedTypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayReference.java new file mode 100644 index 0000000..e298f77 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayReference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * Representation of an array reference + *+ * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IArrayReference extends IReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayTypeReference.java new file mode 100644 index 0000000..75ef4a2 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IArrayTypeReference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IArrayTypeReference extends ISingleTypeReference { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAssignment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAssignment.java new file mode 100644 index 0000000..ee31a8d --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IAssignment.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.core.infer.InferredType; + +/** + * Representation of an assignment expression + *+ * This interface is not intended to be implemented by clients. + *
+* Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IAssignment extends IExpression { + + /** + * get the expression being assigned + * @return expression + */ + IExpression getExpression(); + + /** + * The assignment target + * @return + */ + IExpression getLeftHandSide(); + + IJsDoc getJsDoc(); + + /** + * Set the inferred type of the assignment + * @param inferred type + */ + public void setInferredType(InferredType type); + /** + * Get the inferred type of the assignment + * @return inferred type + */ + public InferredType getInferredType(); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBinaryExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBinaryExpression.java new file mode 100644 index 0000000..47c9186 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBinaryExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * Representation of binary expressions + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IBinaryExpression extends IOperatorExpression{ + public IExpression getLeft(); + public IExpression getRight(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBlock.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBlock.java new file mode 100644 index 0000000..5979000 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBlock.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * Representation of blocks of statements. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IBlock extends IStatement { + public IStatement[] getStatements() ; +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBranchStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBranchStatement.java new file mode 100644 index 0000000..68cd4c5 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBranchStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a branch statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IBranchStatement extends IStatement { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBreakStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBreakStatement.java new file mode 100644 index 0000000..c875f58 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IBreakStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a break statment. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IBreakStatement extends IBranchStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICaseStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICaseStatement.java new file mode 100644 index 0000000..c2e6a0c --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICaseStatement.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a case statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ICaseStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICombinedBinaryExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICombinedBinaryExpression.java new file mode 100644 index 0000000..0fd006a --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICombinedBinaryExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of binary expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ICombinedBinaryExpression extends IBinaryExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICompoundAssignment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICompoundAssignment.java new file mode 100644 index 0000000..27e70d6 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ICompoundAssignment.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + + +/** + * + * Representation of a compound assigment. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ICompoundAssignment extends IAssignment { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IConditionalExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IConditionalExpression.java new file mode 100644 index 0000000..0bebc76 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IConditionalExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a conditional expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IConditionalExpression extends IOperatorExpression { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IConstructorDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IConstructorDeclaration.java new file mode 100644 index 0000000..2dc8647 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IConstructorDeclaration.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a constructor declaration. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IConstructorDeclaration extends IAbstractFunctionDeclaration{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IContinueStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IContinueStatement.java new file mode 100644 index 0000000..fbca0ec --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IContinueStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a continue statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IContinueStatement extends IBranchStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDebuggerStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDebuggerStatement.java new file mode 100644 index 0000000..94c32cd --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDebuggerStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a debugger statement (debugger;). + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IDebuggerStatement extends IStatement { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDoStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDoStatement.java new file mode 100644 index 0000000..203d546 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDoStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a do statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IDoStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDoubleLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDoubleLiteral.java new file mode 100644 index 0000000..b1b9bc1 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IDoubleLiteral.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IDoubleLiteral extends INumberLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEmptyExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEmptyExpression.java new file mode 100644 index 0000000..7786e7b --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEmptyExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of an empty expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IEmptyExpression extends IExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEmptyStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEmptyStatement.java new file mode 100644 index 0000000..b13abe0 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEmptyStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of an empty statement (;). + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IEmptyStatement extends IStatement { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEqualExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEqualExpression.java new file mode 100644 index 0000000..037bbf7 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IEqualExpression.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + + +/** + * + * Representation of = expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IEqualExpression extends IBinaryExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExplicitConstructorCall.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExplicitConstructorCall.java new file mode 100644 index 0000000..c55570f --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExplicitConstructorCall.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of constructor call. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IExplicitConstructorCall extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExpression.java new file mode 100644 index 0000000..d6472df --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Abstract base class for expression elements. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IExpression extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExtendedStringLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExtendedStringLiteral.java new file mode 100644 index 0000000..7f02874 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IExtendedStringLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a string literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IExtendedStringLiteral extends IStringLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFalseLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFalseLiteral.java new file mode 100644 index 0000000..47351ff --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFalseLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of the false literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IFalseLiteral extends IMagicLiteral { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFieldDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFieldDeclaration.java new file mode 100644 index 0000000..e994126 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFieldDeclaration.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IFieldDeclaration extends IAbstractVariableDeclaration{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFieldReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFieldReference.java new file mode 100644 index 0000000..96f88dc --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFieldReference.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a field reference. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IFieldReference extends IReference{ + public IExpression getReceiver(); + char[] getToken(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForInStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForInStatement.java new file mode 100644 index 0000000..c403d99 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForInStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of for .. in statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IForInStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForStatement.java new file mode 100644 index 0000000..03bea0c --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a for statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IForStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForeachStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForeachStatement.java new file mode 100644 index 0000000..aa1fafe --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IForeachStatement.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IForeachStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionCall.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionCall.java new file mode 100644 index 0000000..967f1e0 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionCall.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a function call. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IFunctionCall extends IExpression{ + public char[] getSelector(); + public IExpression[] getArguments(); + public IExpression getReceiver(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionDeclaration.java new file mode 100644 index 0000000..9f90e27 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionDeclaration.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * Representation of a function declaration. + *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IFunctionDeclaration extends IAbstractFunctionDeclaration{ +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionExpression.java new file mode 100644 index 0000000..47e4b7f --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IFunctionExpression.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration; + +/** + * Representation of a function expression ( function (){}). + *+ * This interface is not intended to be implemented by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IFunctionExpression extends IExpression{ + + public void setMethodDeclaration(MethodDeclaration methodDeclaration); + public MethodDeclaration getMethodDeclaration(); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIfStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIfStatement.java new file mode 100644 index 0000000..4d5bdd1 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIfStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of an if statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IIfStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IImportReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IImportReference.java new file mode 100644 index 0000000..ca7fe0e --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IImportReference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IImportReference extends IASTNode{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IInitializer.java new file mode 100644 index 0000000..14b6e84 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IInitializer.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IInitializer extends IFieldDeclaration{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IInstanceOfExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IInstanceOfExpression.java new file mode 100644 index 0000000..7041185 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IInstanceOfExpression.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IInstanceOfExpression extends IOperatorExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIntLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIntLiteral.java new file mode 100644 index 0000000..ad8c50a --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIntLiteral.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IIntLiteral extends INumberLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIntLiteralMinValue.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIntLiteralMinValue.java new file mode 100644 index 0000000..bf53a94 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IIntLiteralMinValue.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IIntLiteralMinValue extends IIntLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDoc.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDoc.java new file mode 100644 index 0000000..665ce92 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDoc.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a jsdoc comment. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDoc extends IASTNode{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocAllocationExpression.java new file mode 100644 index 0000000..45edb20 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocAllocationExpression.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocAllocationExpression extends IAllocationExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArgumentExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArgumentExpression.java new file mode 100644 index 0000000..2f1f3f0 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArgumentExpression.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocArgumentExpression extends IExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArrayQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArrayQualifiedTypeReference.java new file mode 100644 index 0000000..0b1dfa4 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArrayQualifiedTypeReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocArrayQualifiedTypeReference extends IArrayQualifiedTypeReference { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArraySingleTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArraySingleTypeReference.java new file mode 100644 index 0000000..c2608fb --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocArraySingleTypeReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocArraySingleTypeReference extends IArrayTypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocFieldReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocFieldReference.java new file mode 100644 index 0000000..59db014 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocFieldReference.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocFieldReference extends IFieldReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocImplicitTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocImplicitTypeReference.java new file mode 100644 index 0000000..ce93950 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocImplicitTypeReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocImplicitTypeReference extends ITypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocMessageSend.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocMessageSend.java new file mode 100644 index 0000000..6b6d70a --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocMessageSend.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocMessageSend extends IFunctionCall{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocQualifiedTypeReference.java new file mode 100644 index 0000000..913d529 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocQualifiedTypeReference.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocQualifiedTypeReference extends IQualifiedTypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocReturnStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocReturnStatement.java new file mode 100644 index 0000000..71c8e03 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocReturnStatement.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocReturnStatement extends IReturnStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocSingleNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocSingleNameReference.java new file mode 100644 index 0000000..71c45ff --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocSingleNameReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocSingleNameReference extends ISingleNameReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocSingleTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocSingleTypeReference.java new file mode 100644 index 0000000..e1b2039 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IJsDocSingleTypeReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IJsDocSingleTypeReference extends ISingleTypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILabeledStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILabeledStatement.java new file mode 100644 index 0000000..a060b5e --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILabeledStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a labeled statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ILabeledStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IListExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IListExpression.java new file mode 100644 index 0000000..4f28b28 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IListExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of list expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IListExpression extends IExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILiteral.java new file mode 100644 index 0000000..8698068 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILiteral.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Abstract base class for literals. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ILiteral extends IExpression { + + public abstract char[] source(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILocalDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILocalDeclaration.java new file mode 100644 index 0000000..4a92fe6 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ILocalDeclaration.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite; +import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding; + +/** + * + * Representation of a local var declaration. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ILocalDeclaration extends InvocationSite, IAbstractVariableDeclaration { + public void setBinding(LocalVariableBinding binding); + public LocalVariableBinding getBinding(); + /** + * Get the initialization expression of the var as an assignment + * @return initialization assignment expression or null + */ + public IAssignment getAssignment(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IMagicLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IMagicLiteral.java new file mode 100644 index 0000000..a6e87f6 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IMagicLiteral.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IMagicLiteral extends ILiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INameReference.java new file mode 100644 index 0000000..7b289bf --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INameReference.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Abstract base class for references. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface INameReference extends IReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INullLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INullLiteral.java new file mode 100644 index 0000000..c58d606 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INullLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of the null literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface INullLiteral extends IMagicLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INumberLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INumberLiteral.java new file mode 100644 index 0000000..dc50387 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/INumberLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a numeric literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface INumberLiteral extends ILiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IOR_OR_Expression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IOR_OR_Expression.java new file mode 100644 index 0000000..a9d7966 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IOR_OR_Expression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of an or or (||) expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IOR_OR_Expression extends IBinaryExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IObjectLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IObjectLiteral.java new file mode 100644 index 0000000..711c582 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IObjectLiteral.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +import org.eclipse.wst.jsdt.core.infer.InferredType; + +/** + * + * Representation of an Object literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IObjectLiteral extends IExpression { + public InferredType getInferredType(); + public void setInferredType(InferredType type); + public IObjectLiteralField[] getFields(); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IObjectLiteralField.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IObjectLiteralField.java new file mode 100644 index 0000000..c0ac65b --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IObjectLiteralField.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of an object literal field. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IObjectLiteralField extends IExpression{ + public IExpression getFieldName(); + public IExpression getInitializer(); + public IJsDoc getJsDoc(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IOperatorExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IOperatorExpression.java new file mode 100644 index 0000000..37a7c78 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IOperatorExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of an Operator expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IOperatorExpression extends IExpression { + public int getOperator(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IPostfixExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IPostfixExpression.java new file mode 100644 index 0000000..1a236e5 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IPostfixExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a postfix expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IPostfixExpression extends ICompoundAssignment{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IPrefixExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IPrefixExpression.java new file mode 100644 index 0000000..e1ab94f --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IPrefixExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a prefix expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IPrefixExpression extends ICompoundAssignment{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IProgramElement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IProgramElement.java new file mode 100644 index 0000000..5987ba3 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IProgramElement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Abstract base class for most AST nodes. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IProgramElement extends IASTNode{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedAllocationExpression.java new file mode 100644 index 0000000..bd79de4 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedAllocationExpression.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IQualifiedAllocationExpression extends IAllocationExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedNameReference.java new file mode 100644 index 0000000..1bed12c --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedNameReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IQualifiedNameReference extends INameReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedThisReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedThisReference.java new file mode 100644 index 0000000..b7a7abc --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedThisReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IQualifiedThisReference extends IThisReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedTypeReference.java new file mode 100644 index 0000000..50df1b6 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IQualifiedTypeReference.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IQualifiedTypeReference extends ITypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IReference.java new file mode 100644 index 0000000..0e37db4 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IReference.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Abstract base class for references. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IReference extends IExpression{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IRegExLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IRegExLiteral.java new file mode 100644 index 0000000..5d7001b --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IRegExLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a regular expression literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IRegExLiteral extends ILiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IReturnStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IReturnStatement.java new file mode 100644 index 0000000..6dabd13 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IReturnStatement.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a return statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IReturnStatement extends IStatement { + + IExpression getExpression(); + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IScriptFileDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IScriptFileDeclaration.java new file mode 100644 index 0000000..1abb9a0 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IScriptFileDeclaration.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of javascript file. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IScriptFileDeclaration extends IASTNode{ + + IProgramElement []getStatements(); + + /** + * get the filename for the script if it can be determined + * @return the scripts file name, this could be null + */ + char[] getFileName(); + + /** + * get the inference ID for the script if it is located in a container that specified an Inference ID + * @return the inference ID for the script, could be null + */ + String getInferenceID(); + + public void addImport(char [] importName, int startPosition, int endPosition, int nameStartPosition); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISingleNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISingleNameReference.java new file mode 100644 index 0000000..b037d88 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISingleNameReference.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of name reference. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ISingleNameReference extends INameReference{ + public char[] getToken(); + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISingleTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISingleTypeReference.java new file mode 100644 index 0000000..b0a5bfb --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISingleTypeReference.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ISingleTypeReference extends ITypeReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStatement.java new file mode 100644 index 0000000..3eda7cb --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Abstract base for statements. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IStatement extends IProgramElement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStringLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStringLiteral.java new file mode 100644 index 0000000..7dc6ab7 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStringLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a string literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IStringLiteral extends ILiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStringLiteralConcatenation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStringLiteralConcatenation.java new file mode 100644 index 0000000..447cf19 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IStringLiteralConcatenation.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a string literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IStringLiteralConcatenation extends IStringLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISubRoutineStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISubRoutineStatement.java new file mode 100644 index 0000000..afca555 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISubRoutineStatement.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ISubRoutineStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISuperReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISuperReference.java new file mode 100644 index 0000000..af53982 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISuperReference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ISuperReference extends IThisReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISwitchStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISwitchStatement.java new file mode 100644 index 0000000..389b8e9 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ISwitchStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a switch statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ISwitchStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IThisReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IThisReference.java new file mode 100644 index 0000000..6d61e90 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IThisReference.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a 'this' reference . + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IThisReference extends IReference{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IThrowStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IThrowStatement.java new file mode 100644 index 0000000..2102d53 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IThrowStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a throw statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IThrowStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITrueLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITrueLiteral.java new file mode 100644 index 0000000..f6e91f8 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITrueLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of the 'true' literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ITrueLiteral extends IMagicLiteral{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITryStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITryStatement.java new file mode 100644 index 0000000..c88fef6 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITryStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a try statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ITryStatement extends ISubRoutineStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITypeDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITypeDeclaration.java new file mode 100644 index 0000000..af5943b --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITypeDeclaration.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ITypeDeclaration extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITypeReference.java new file mode 100644 index 0000000..ed76eb8 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/ITypeReference.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface ITypeReference extends IExpression { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IUnaryExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IUnaryExpression.java new file mode 100644 index 0000000..3bbf6eb --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IUnaryExpression.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a unary expression. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IUnaryExpression extends IOperatorExpression{ + public IExpression getExpression(); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IUndefinedLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IUndefinedLiteral.java new file mode 100644 index 0000000..2c75df5 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IUndefinedLiteral.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a the 'undefined' literal. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IUndefinedLiteral extends IMagicLiteral { + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IWhileStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IWhileStatement.java new file mode 100644 index 0000000..94e9276 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IWhileStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of a while statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IWhileStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IWithStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IWithStatement.java new file mode 100644 index 0000000..d9ed8f3 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/ast/IWithStatement.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.ast; + +/** + * + * Representation of the with statement. + *+ * This interface is not intended to be implemented by clients. + *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ + +public interface IWithStatement extends IStatement{ + +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/BuildContext.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/BuildContext.java new file mode 100644 index 0000000..e14658c --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/BuildContext.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.compiler; + +import org.eclipse.core.resources.IFile; +import org.eclipse.wst.jsdt.internal.core.builder.ValidationParticipantResult; +import org.eclipse.wst.jsdt.internal.core.builder.SourceFile; + +/** + * The context of a validation event that is notified to interested validation + * participants when {@link ValidationParticipant#buildStarting(BuildContext[], boolean) a build is starting. + *+ * This class is not intended to be instanciated or subclassed by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class BuildContext extends ValidationParticipantResult { + +/** + * Creates a build context for the given source file. + *+ * This constructor is not intended to be called by clients. + *
+ * + * @param sourceFile the source file being built + */ +public BuildContext(SourceFile sourceFile) { + super(sourceFile); +} + +/** + * Returns the contents of the javaScript unit. + * + * @return the contents of the javaScript unit + */ +public char[] getContents() { + return this.sourceFile.getContents(); +} + +/** + * Returns theIFile
representing the javaScript unit.
+ *
+ * @return the IFile
representing the javaScript unit
+ */
+public IFile getFile() {
+ return this.sourceFile.resource;
+}
+
+/**
+ * Record the added/changed generated files that need to be compiled.
+ *
+ * @param addedGeneratedFiles the added/changed files
+ */
+public void recordAddedGeneratedFiles(IFile[] addedGeneratedFiles) {
+ int length2 = addedGeneratedFiles.length;
+ if (length2 == 0) return;
+
+ int length1 = this.addedFiles == null ? 0 : this.addedFiles.length;
+ IFile[] merged = new IFile[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.addedFiles, 0, merged, 0, length1);
+ System.arraycopy(addedGeneratedFiles, 0, merged, length1, length2);
+ this.addedFiles = merged;
+}
+
+/**
+ * Record the generated files that need to be deleted.
+ *
+ * @param deletedGeneratedFiles the files that need to be deleted
+ */
+public void recordDeletedGeneratedFiles(IFile[] deletedGeneratedFiles) {
+ int length2 = deletedGeneratedFiles.length;
+ if (length2 == 0) return;
+
+ int length1 = this.deletedFiles == null ? 0 : this.deletedFiles.length;
+ IFile[] merged = new IFile[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.deletedFiles, 0, merged, 0, length1);
+ System.arraycopy(deletedGeneratedFiles, 0, merged, length1, length2);
+ this.deletedFiles = merged;
+}
+
+/**
+ * Record the fully-qualified type names of any new dependencies, each name is of the form "p1.p2.A.B".
+ *
+ * @param typeNameDependencies the fully-qualified type names of new dependencies
+ */
+public void recordDependencies(String[] typeNameDependencies) {
+ int length2 = typeNameDependencies.length;
+ if (length2 == 0) return;
+
+ int length1 = this.dependencies == null ? 0 : this.dependencies.length;
+ String[] merged = new String[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.dependencies, 0, merged, 0, length1);
+ System.arraycopy(typeNameDependencies, 0, merged, length1, length2);
+ this.dependencies = merged;
+}
+
+/**
+ * Record new problems to report against this compilationUnit.
+ * Markers are persisted for these problems only for the declared managed marker type
+ * (see the 'validationParticipant' extension point).
+ *
+ * @param newProblems the problems to report
+ */
+public void recordNewProblems(CategorizedProblem[] newProblems) {
+ int length2 = newProblems.length;
+ if (length2 == 0) return;
+
+ int length1 = this.problems == null ? 0 : this.problems.length;
+ CategorizedProblem[] merged = new CategorizedProblem[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.problems, 0, merged, 0, length1);
+ System.arraycopy(newProblems, 0, merged, length1, length2);
+ this.problems = merged;
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CategorizedProblem.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CategorizedProblem.java
new file mode 100644
index 0000000..9afa3eb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CategorizedProblem.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.compiler;
+
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblem;
+
+/**
+ * Richer description of a JavaScript problem, as detected by the compiler or some of the underlying
+ * technology reusing the compiler. With the introduction of validationParticipant
,
+ * the simpler problem interface IProblem
did not carry enough information to better
+ * separate and categorize JavaScript problems. In order to minimize impact on existing API, JavaScript problems
+ * are still passed around as IProblem
, though actual implementations should explicitly
+ * extend CategorizedProblem
. Participants can produce their own problem definitions,
+ * and given these are categorized problems, they can be better handled by clients (such as user
+ * interface).
+ *
+ * A categorized problem provides access to:
+ * IProblem
, IProblem
for backward compatibility reason.
+ * It is intended that CategorizedProblem
will be subclassed for custom problem implementation when
+ * participating in compilation operations, so as to allow participant to contribute their own marker types, and thus
+ * defining their own domain specific problem/category IDs.
+ *
+ * Note: standard JavaScript problems produced by JavaScript default tooling will set the
+ * marker IMarker#GENERATED_BY attribute to JavaBuilder#GENERATED_BY; compiler
+ * participants may specify the IMarker#GENERATED_BY attribute of their markers
+ * by adding it to the extra marker attributes of the problems they generate;
+ * markers resulting from compiler participants' problems that do not have the
+ * IMarker#GENERATED_BY extra attribute set do not have the IMarker#GENERATED_BY
+ * attribute set either.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class CategorizedProblem implements IProblem {
+
+ /**
+ * List of standard category IDs used by JavaScript problems, more categories will be added
+ * in the future.
+ */
+ public static final int CAT_UNSPECIFIED = 0;
+ /** Category for problems related to buildpath */
+ public static final int CAT_BUILDPATH = 10;
+ /** Category for fatal problems related to syntax */
+ public static final int CAT_SYNTAX = 20;
+ /** Category for fatal problems in import statements */
+ public static final int CAT_IMPORT = 30;
+ /** Category for fatal problems related to types, could be addressed by some type change */
+ public static final int CAT_TYPE = 40;
+ /** Category for fatal problems related to type members, could be addressed by some field or method change */
+ public static final int CAT_MEMBER = 50;
+ /** Category for fatal problems which could not be addressed by external changes, but require an edit to be addressed */
+ public static final int CAT_INTERNAL = 60;
+ /** Category for optional problems in Javadoc */
+ public static final int CAT_JAVADOC = 70;
+ /** Category for optional problems related to coding style practices */
+ public static final int CAT_CODE_STYLE = 80;
+ /** Category for optional problems related to potential programming flaws */
+ public static final int CAT_POTENTIAL_PROGRAMMING_PROBLEM = 90;
+ /** Category for optional problems related to naming conflicts */
+ public static final int CAT_NAME_SHADOWING_CONFLICT = 100;
+ /** Category for optional problems related to unnecessary code */
+ public static final int CAT_UNNECESSARY_CODE = 120;
+ /** Category for optional problems related to access restrictions */
+ public static final int CAT_RESTRICTION = 150;
+
+/**
+ * Returns an integer identifying the category of this problem. Categories, like problem IDs are
+ * defined in the context of some marker type. Custom implementations of CategorizedProblem
+ * may choose arbitrary values for problem/category IDs, as long as they are associated with a different
+ * marker type.
+ * Standard JavaScript problem markers (i.e. marker type is "org.eclipse.wst.jsdt.core.problem") carry an
+ * attribute "categoryId" persisting the originating problem category ID as defined by this method).
+ * @return id - an integer identifying the category of this problem
+ */
+public abstract int getCategoryID();
+
+/**
+ * Returns the marker type associated to this problem, if it gets persisted into a marker by the JavaBuilder
+ * Standard JavaScript problems are associated to marker type "org.eclipse.wst.jsdt.core.problem").
+ * Note: problem markers are expected to extend "org.eclipse.core.resources.problemmarker" marker type.
+ * @return the type of the marker which would be associated to the problem
+ */
+public abstract String getMarkerType();
+
+/**
+ * Returns the names of the extra marker attributes associated to this problem when persisted into a marker
+ * by the JavaBuilder. Extra attributes are only optional, and are allowing client customization of generated
+ * markers. By default, no EXTRA attributes is persisted, and a categorized problem only persists the following attributes:
+ * IMarker#MESSAGE
-> {@link IProblem#getMessage()}IMarker#SEVERITY
-> IMarker#SEVERITY_ERROR
or
+ * IMarker#SEVERITY_WARNING
depending on {@link IProblem#isError()} or {@link IProblem#isWarning()}IJavaScriptModelMarker#ID
-> {@link IProblem#getID()}IMarker#CHAR_START
-> {@link IProblem#getSourceStart()}IMarker#CHAR_END
-> {@link IProblem#getSourceEnd()}IMarker#LINE_NUMBER
-> {@link IProblem#getSourceLineNumber()}IJavaScriptModelMarker#ARGUMENTS
-> some String[]
used to compute quickfixes IJavaScriptModelMarker#CATEGORY_ID
-> {@link CategorizedProblem#getCategoryID()}IMarker#setAttributes(String[], Object[])
,
+ * and there must be as many names as values according to {@link #getExtraMarkerAttributeValues()}.
+ * Note that extra marker attributes will be inserted after default ones (as described in {@link CategorizedProblem#getMarkerType()},
+ * and thus could be used to override defaults.
+ * @return the names of the corresponding marker attributes
+ */
+public String[] getExtraMarkerAttributeNames() {
+ return CharOperation.NO_STRINGS;
+}
+
+/**
+ * Returns the respective values for the extra marker attributes associated to this problem when persisted into
+ * a marker by the JavaBuilder. Each value must correspond to a matching attribute name, as defined by
+ * {@link #getExtraMarkerAttributeNames()}.
+ * The values must be eligible for marker creation, as defined by IMarker#setAttributes(String[], Object[])
.
+ * @return the values of the corresponding extra marker attributes
+ */
+public Object[] getExtraMarkerAttributeValues() {
+ return DefaultProblem.EMPTY_VALUES;
+}
+
+public void setMessage(String msg)
+{
+
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java
new file mode 100644
index 0000000..4dc1e2d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/CharOperation.java
@@ -0,0 +1,3433 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Luiz-Otavio Zorzella + * This class is not intended to be instantiated or subclassed by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class CharOperation { + + /** + * Constant for an empty char array + */ + public static final char[] NO_CHAR = new char[0]; + + /** + * Constant for an empty char array with two dimensions. + */ + public static final char[][] NO_CHAR_CHAR = new char[0][]; + + /** + * Constant for an empty String array. + */ + public static final String[] NO_STRINGS = new String[0]; + +/** + * Answers a new array with appending the suffix character at the end of the array. + *+ * array = { 'a', 'b' } + * suffix = 'c' + * => result = { 'a', 'b' , 'c' } + *+ *
+ * array = null + * suffix = 'c' + * => result = { 'c' } + *
+ * target = { 'a', 'b', '0' } + * index = 2 + * array = { 'c', 'd' } + * start = 0 + * end = 1 + * => result = { 'a', 'b' , 'c' } + *+ *
+ * target = { 'a', 'b' } + * index = 2 + * array = { 'c', 'd' } + * start = 0 + * end = 1 + * => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array) + *
+ * target = { 'a', 'b', 'c' } + * index = 1 + * array = { 'c', 'd', 'e', 'f' } + * start = 1 + * end = 4 + * => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array) + *
+ * first = null + * second = null + * => result = null + *+ *
+ * first = { { ' a' } } + * second = null + * => result = { { ' a' } } + *+ *
+ * first = null + * second = { { ' a' } } + * => result = { { ' a' } } + *+ *
+ * first = { { ' b' } } + * second = { { ' a' } } + * => result = { { ' b' }, { ' a' } } + *+ *
+ * pattern = { 'N', 'P', 'E' } + * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * result => true + *+ *
+ * pattern = { 'N', 'P', 'E' } + * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * result => true + *+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' } + * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * result => true + *+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' } + * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * result => false + *+ *
+ * pattern = { 'n', p', 'e' } + * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * result => false + *+ *
+ * pattern = { 'N', 'P', 'E' } + * patternStart = 0 + * patternEnd = 3 + * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * nameStart = 0 + * nameEnd = 20 + * result => true + *+ *
+ * pattern = { 'N', 'P', 'E' } + * patternStart = 0 + * patternEnd = 3 + * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * nameStart = 0 + * nameEnd = 21 + * result => true + *+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' } + * patternStart = 0 + * patternEnd = 6 + * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * nameStart = 0 + * nameEnd = 20 + * result => true + *+ *
+ * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' } + * patternStart = 0 + * patternEnd = 6 + * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * nameStart = 0 + * nameEnd = 21 + * result => false + *+ *
+ * pattern = { 'n', p', 'e' } + * patternStart = 0 + * patternEnd = 3 + * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' } + * nameStart = 0 + * nameEnd = 20 + * result => false + *+ *
+ * first = null + * second = { 'a' } + * => result = { { ' a' } } + *+ *
+ * first = { { ' a' } } + * second = null + * => result = { { ' a' } } + *+ *
+ * first = { { ' a' } } + * second = { ' b' } + * => result = { { ' a' } , { ' b' } } + *+ *
+ * For example: + *
+ * array = null + * prefix = null + * => result = NullPointerException + *+ *
+ * array = { 'a', 'b', 'c', 'd', 'e' } + * prefix = { 'a', 'b', 'c'} + * => result = 0 + *+ *
+ * array = { 'a', 'b', 'c', 'd', 'e' } + * prefix = { 'a', 'B', 'c'} + * => result = 32 + *+ *
+ * array = { 'd', 'b', 'c', 'd', 'e' } + * prefix = { 'a', 'b', 'c'} + * => result = 3 + *+ *
+ * array = { 'a', 'b', 'c', 'd', 'e' } + * prefix = { 'd', 'b', 'c'} + * => result = -3 + *+ *
+ * array = { 'a', 'a', 'c', 'd', 'e' } + * prefix = { 'a', 'e', 'c'} + * => result = -4 + *+ *
+ * first = null + * second = { 'a' } + * => result = { ' a' } + *+ *
+ * first = { ' a' } + * second = null + * => result = { ' a' } + *+ *
+ * first = { ' a' } + * second = { ' b' } + * => result = { ' a' , ' b' } + *+ *
+ * first = null + * second = { 'a' } + * third = { 'b' } + * => result = { ' a', 'b' } + *+ *
+ * first = { 'a' } + * second = null + * third = { 'b' } + * => result = { ' a', 'b' } + *+ *
+ * first = { 'a' } + * second = { 'b' } + * third = null + * => result = { ' a', 'b' } + *+ *
+ * first = null + * second = null + * third = null + * => result = null + *+ *
+ * first = { 'a' } + * second = { 'b' } + * third = { 'c' } + * => result = { 'a', 'b', 'c' } + *+ *
+ * first = null + * second = { 'a' } + * separator = '/' + * => result = { ' a' } + *+ *
+ * first = { ' a' } + * second = null + * separator = '/' + * => result = { ' a' } + *+ *
+ * first = { ' a' } + * second = { ' b' } + * separator = '/' + * => result = { ' a' , '/', 'b' } + *+ *
+ * first = null + * sep1 = '/' + * second = { 'a' } + * sep2 = ':' + * third = { 'b' } + * => result = { ' a' , ':', 'b' } + *+ *
+ * first = { 'a' } + * sep1 = '/' + * second = null + * sep2 = ':' + * third = { 'b' } + * => result = { ' a' , '/', 'b' } + *+ *
+ * first = { 'a' } + * sep1 = '/' + * second = { 'b' } + * sep2 = ':' + * third = null + * => result = { ' a' , '/', 'b' } + *+ *
+ * first = { 'a' } + * sep1 = '/' + * second = { 'b' } + * sep2 = ':' + * third = { 'c' } + * => result = { ' a' , '/', 'b' , ':', 'c' } + *+ *
+ * prefix = 'a' + * array = { 'b' } + * suffix = 'c' + * => result = { 'a', 'b' , 'c' } + *+ *
+ * prefix = 'a' + * array = null + * suffix = 'c' + * => result = { 'a', 'c' } + *
+ * name = { 'c' } + * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' , '.', 'c' } + *+ *
+ * name = null + * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' } + *
+ * name = { ' c' } + * array = null + * separator = '.' + * => result = { 'c' } + *
+ * name = { 'c' } + * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' , '.', 'c' } + *+ *
+ * name = null + * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' } + *
+ * name = { ' c' } + * array = null + * separator = '.' + * => result = { 'c' } + *
+ * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' } + *+ *
+ * array = null + * separator = '.' + * => result = { } + *
NOTE: This implementation ignores any elements in the given array that are empty.
+ * + * @param array the given array + * @param separator the given separator + * + * @return the concatenation of the given array parts using the given separator between each part + * + * @see #concatWith(char[][], char, boolean) + */ +public static final char[] concatWith(char[][] array, char separator) { + return concatWith(array, separator, true); +} + +/** + * Answers the concatenation of the given array parts using the given separator between each part. + *+ * array = { { 'a' }, { 'b' } } + * separator = '.' + * => result = { 'a', '.', 'b' } + *+ *
+ * array = null + * separator = '.' + * => result = { } + *
This implementation allows the caller to decide if empty elements in the array should be skipped or not
+ * + * @param array char string array to concatenate with itself + * @param separator the separator to use between each element of the char string array + * @param ignoreEmptyElementstrue
to skip any empty elements in the char string array,
+ * false
to include an empty element in the return char string
+ *
+ * @return the concatenation of the given array parts using the given separator between each part
+ */
+public static final char[] concatWith(char[][] array, char separator, boolean ignoreEmptyElements) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return CharOperation.NO_CHAR;
+
+ int size = length - 1;
+ int index = length;
+ while (--index >= 0) {
+ if (array[index].length == 0 && ignoreEmptyElements)
+ size--;
+ else
+ size += array[index].length;
+ }
+ if (size <= 0)
+ return CharOperation.NO_CHAR;
+ char[] result = new char[size];
+ index = length;
+ while (--index >= 0) {
+ length = array[index].length;
+ if (length > 0 || (length == 0 && !ignoreEmptyElements)) {
+ System.arraycopy(
+ array[index],
+ 0,
+ result,
+ (size -= length),
+ length);
+ if (--size >= 0)
+ result[size] = separator;
+ }
+ }
+ return result;
+}
+
+/**
+ * Answers true if the array contains an occurrence of character, false otherwise.
+ *
+ * + * character = 'c' + * array = { { ' a' }, { ' b' } } + * result => false + *+ *
+ * character = 'a' + * array = { { ' a' }, { ' b' } } + * result => true + *+ *
+ * character = 'c' + * array = { ' b' } + * result => false + *+ *
+ * character = 'a' + * array = { ' a' , ' b' } + * result => true + *+ *
+ * characters = { 'c', 'd' } + * array = { 'a', ' b' } + * result => false + *+ *
+ * characters = { 'c', 'd' } + * array = { 'a', ' b', 'c' } + * result => true + *+ *
+ * array = { 'a', 'b', 'c', 'd' } + * toBeFound = { 'b', 'c' } + * result => false + *+ *
+ * array = { 'a', 'b', 'c' } + * toBeFound = { 'b', 'c' } + * result => true + *+ *
+ * first = null + * second = null + * result => true + *+ *
+ * first = { { } } + * second = null + * result => false + *+ *
+ * first = { { 'a' } } + * second = { { 'a' } } + * result => true + *+ *
+ * first = { { 'A' } } + * second = { { 'a' } } + * result => false + *+ *
+ * first = null + * second = null + * isCaseSensitive = true + * result => true + *+ *
+ * first = { { } } + * second = null + * isCaseSensitive = true + * result => false + *+ *
+ * first = { { 'A' } } + * second = { { 'a' } } + * isCaseSensitive = true + * result => false + *+ *
+ * first = { { 'A' } } + * second = { { 'a' } } + * isCaseSensitive = false + * result => true + *+ *
+ * first = null + * second = null + * result => true + *+ *
+ * first = { } + * second = null + * result => false + *+ *
+ * first = { 'a' } + * second = { 'a' } + * result => true + *+ *
+ * first = { 'a' } + * second = { 'A' } + * result => false + *+ *
+ * first = null + * second = null + * secondStart = 0 + * secondEnd = 0 + * result => true + *+ *
+ * first = { } + * second = null + * secondStart = 0 + * secondEnd = 0 + * result => false + *+ *
+ * first = { 'a' } + * second = { 'a' } + * secondStart = 0 + * secondEnd = 1 + * result => true + *+ *
+ * first = { 'a' } + * second = { 'A' } + * secondStart = 0 + * secondEnd = 1 + * result => false + *+ *
Answers true if the first array is identical character by character to a portion of the second array
+ * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false. The equality could be either
+ * case sensitive or case insensitive according to the value of the isCaseSensitive
parameter.
+ *
For example:
+ *+ * first = null + * second = null + * secondStart = 0 + * secondEnd = 0 + * isCaseSensitive = false + * result => true + *+ *
+ * first = { } + * second = null + * secondStart = 0 + * secondEnd = 0 + * isCaseSensitive = false + * result => false + *+ *
+ * first = { 'a' } + * second = { 'a' } + * secondStart = 0 + * secondEnd = 1 + * isCaseSensitive = true + * result => true + *+ *
+ * first = { 'a' } + * second = { 'A' } + * secondStart = 0 + * secondEnd = 1 + * isCaseSensitive = true + * result => false + *+ *
+ * first = { 'a' } + * second = { 'A' } + * secondStart = 0 + * secondEnd = 1 + * isCaseSensitive = false + * result => true + *+ *
+ * first = null + * second = null + * isCaseSensitive = true + * result => true + *+ *
+ * first = { } + * second = null + * isCaseSensitive = true + * result => false + *+ *
+ * first = { 'A' } + * second = { 'a' } + * isCaseSensitive = true + * result => false + *+ *
+ * first = { 'A' } + * second = { 'a' } + * isCaseSensitive = false + * result => true + *+ *
+ * fragment = { 'b', 'c' , 'd' } + * name = { 'a', 'b', 'c' , 'd' } + * startIndex = 1 + * isCaseSensitive = true + * result => true + *+ *
+ * fragment = { 'b', 'c' , 'd' } + * name = { 'a', 'b', 'C' , 'd' } + * startIndex = 1 + * isCaseSensitive = true + * result => false + *+ *
+ * fragment = { 'b', 'c' , 'd' } + * name = { 'a', 'b', 'C' , 'd' } + * startIndex = 0 + * isCaseSensitive = false + * result => false + *+ *
+ * fragment = { 'b', 'c' , 'd' } + * name = { 'a', 'b'} + * startIndex = 0 + * isCaseSensitive = true + * result => false + *+ *
+ * c = ' ' + * result => true + *+ *
+ * c = '\u3000' + * result => false + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * result => 2 + *+ *
+ * toBeFound = 'e' + * array = { ' a', 'b', 'c', 'd' } + * result => -1 + *+ *
+ * toBeFound = { 'c' } + * array = { ' a', 'b', 'c', 'd' } + * result => 2 + *+ *
+ * toBeFound = { 'e' } + * array = { ' a', 'b', 'c', 'd' } + * result => -1 + *+ *
+ * toBeFound = { 'c' } + * array = { ' a', 'b', 'c', 'd' } + * result => 2 + *+ *
+ * toBeFound = { 'e' } + * array = { ' a', 'b', 'c', 'd' } + * result => -1 + *+ *
+ * toBeFound = { 'c' } + * array = { ' a', 'b', 'c', 'd' } + * result => 2 + *+ *
+ * toBeFound = { 'e' } + * array = { ' a', 'b', 'c', 'd' } + * result => -1 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * start = 2 + * result => 2 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * start = 3 + * result => -1 + *+ *
+ * toBeFound = 'e' + * array = { ' a', 'b', 'c', 'd' } + * start = 1 + * result => -1 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * start = 2 + * result => 2 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * start = 3 + * result => -1 + *+ *
+ * toBeFound = 'e' + * array = { ' a', 'b', 'c', 'd' } + * start = 1 + * result => -1 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' , 'c', 'e' } + * result => 4 + *+ *
+ * toBeFound = 'e' + * array = { ' a', 'b', 'c', 'd' } + * result => -1 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * startIndex = 2 + * result => 2 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd', 'e' } + * startIndex = 3 + * result => -1 + *+ *
+ * toBeFound = 'e' + * array = { ' a', 'b', 'c', 'd' } + * startIndex = 0 + * result => -1 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd' } + * startIndex = 2 + * endIndex = 2 + * result => 2 + *+ *
+ * toBeFound = 'c' + * array = { ' a', 'b', 'c', 'd', 'e' } + * startIndex = 3 + * endIndex = 4 + * result => -1 + *+ *
+ * toBeFound = 'e' + * array = { ' a', 'b', 'c', 'd' } + * startIndex = 0 + * endIndex = 3 + * result => -1 + *+ *
+ * lastSegment("my.namespace.Object".toCharArray(),'.') --> Object + *+ * + * @param array the array + * @param separator the given separator + * @return the last portion of a name given a separator + * @throws NullPointerException if array is null + */ +final static public char[] lastSegment(char[] array, char separator) { + int pos = lastIndexOf(separator, array); + if (pos < 0) + return array; + return subarray(array, pos + 1, array.length); +} + +/** + * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching + * accepts wild-cards '*' and '?'. + * + * When not case sensitive, the pattern is assumed to already be lowercased, the + * name will be lowercased character per character as comparing. + * If name is null, the answer is false. + * If pattern is null, the answer is true if name is not null. + *
+ * pattern = { '?', 'b', '*' } + * name = { 'a', 'b', 'c' , 'd' } + * isCaseSensitive = true + * result => true + *+ *
+ * pattern = { '?', 'b', '?' } + * name = { 'a', 'b', 'c' , 'd' } + * isCaseSensitive = true + * result => false + *+ *
+ * pattern = { 'b', '*' } + * name = { 'a', 'b', 'c' , 'd' } + * isCaseSensitive = true + * result => false + *+ *
+ * pattern = { '?', 'b', '*' } + * patternStart = 1 + * patternEnd = 3 + * name = { 'a', 'b', 'c' , 'd' } + * nameStart = 1 + * nameEnd = 4 + * isCaseSensitive = true + * result => true + *+ *
+ * pattern = { '?', 'b', '*' } + * patternStart = 1 + * patternEnd = 2 + * name = { 'a', 'b', 'c' , 'd' } + * nameStart = 1 + * nameEnd = 2 + * isCaseSensitive = true + * result => false + *+ *
+ * toBeFound = 'b' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => 3 + *+ *
+ * toBeFound = 'c' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => 0 + *+ *
+ * toBeFound = 'b' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * start = 2 + * result => 2 + *+ *
+ * toBeFound = 'c' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * start = 0 + * result => 0 + *+ *
+ * prefix = { 'a' , 'b' } + * name = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => true + *+ *
+ * prefix = { 'a' , 'c' } + * name = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => false + *+ *
+ * prefix = { 'a' , 'B' } + * name = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * isCaseSensitive = false + * result => true + *+ *
+ * prefix = { 'a' , 'B' } + * name = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * isCaseSensitive = true + * result => false + *+ *
+ * array = { 'a' , 'b', 'b', 'c', 'b', 'a' } + * toBeRemoved = 'b' + * return { 'a' , 'c', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeRemoved = 'c' + * return array + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeReplaced = 'b' + * replacementChar = 'a' + * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeReplaced = 'c' + * replacementChar = 'a' + * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' } + * toBeReplaced = { 'b', 'c' } + * replacementChar = 'a' + * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a', 'a', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' } + * toBeReplaced = { 'b', 'c' } + * replacementChar = 'a' + * start = 4 + * end = 8 + * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'c', 'a', 'a', 'a', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeReplaced = { 'b' } + * replacementChar = { 'a', 'a' } + * result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeReplaced = { 'c' } + * replacementChar = { 'a' } + * result => { 'a' , 'b', 'b', 'a', 'b', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeReplaced = 'b' + * replacementChar = 'a' + * result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' } + *+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * toBeReplaced = 'c' + * replacementChar = 'a' + * result => The original array that remains unchanged. + *+ *
+ * divider = 'b' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => { { 'a' }, { }, { 'a' }, { 'a' } } + *+ *
+ * divider = 'c' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } } + *+ *
+ * divider = 'b' + * array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' } + * result => { { 'a' }, { }, { 'a' }, { 'a' } } + *+ *
+ * divider = 'c' + * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' } + * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } } + *+ *
+ * divider = 'b' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => { { 'a' }, { }, { 'a' }, { 'a' } } + *+ *
+ * divider = 'c' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } } + *+ *
+ * divider = 'c' + * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' } + * result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } } + *+ *
+ * divider = 'b' + * array = { 'a' , 'b', 'b', 'a', 'b', 'a' } + * start = 2 + * end = 5 + * result => { { }, { 'a' }, { } } + *+ *
+ * array = { { 'a' } , { 'b' } } + * start = 0 + * end = 1 + * result => { { 'a' } } + *+ *
+ * array = { { 'a' } , { 'b' } } + * start = 0 + * end = -1 + * result => { { 'a' }, { 'b' } } + *+ *
+ * array = { 'a' , 'b' } + * start = 0 + * end = 1 + * result => { 'a' } + *+ *
+ * array = { 'a', 'b' } + * start = 0 + * end = -1 + * result => { 'a' , 'b' } + *+ *
+ * chars = { 'a' , 'b' } + * result => { 'a' , 'b' } + *+ *
+ * array = { 'A', 'b' } + * result => { 'a' , 'b' } + *+ *
+ * chars = { ' ', 'a' , 'b', ' ', ' ' } + * result => { 'a' , 'b' } + *+ *
+ * array = { 'A', 'b' } + * result => { 'A' , 'b' } + *+ *
+ * array = { { 'a' } , { 'b' } } + * result => "a.b" + *+ *
+ * array = { { ' ', 'a' } , { 'b' } } + * result => " a.b" + *+ *
ToolFactory
.
+ * The scanner is responsible for tokenizing a given source, providing information about
+ * the nature of the token read, its positions and source equivalent.
+ *
+ * When the scanner has finished tokenizing, it answers an EOF token (
+ * ITerminalSymbols#TokenNameEOF
.
+ *
+ * When encountering lexical errors, an InvalidInputException
is thrown.
+ *
+ * This interface is not intended to be implemented by clients. + *
+ * + * @see org.eclipse.wst.jsdt.core.ToolFactory + * @see ITerminalSymbols + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface IScanner { + + /** + * Answers the current identifier source, after unicode escape sequences have + * been translated into unicode characters. + * For example, if original source was\\u0061bc
then it will answer abc
.
+ *
+ * @return the current identifier source, after unicode escape sequences have
+ * been translated into unicode characters
+ */
+ char[] getCurrentTokenSource();
+
+ /**
+ * Answers the current identifier source, before unicode escape sequences have
+ * been translated into unicode characters.
+ * For example, if original source was \\u0061bc
then it will answer \\u0061bc
.
+ *
+ * @return the current identifier source, before unicode escape sequences have
+ * been translated into unicode characters
+ * @since 2.1
+ */
+ char[] getRawTokenSource();
+
+ /**
+ * Answers the starting position of the current token inside the original source.
+ * This position is zero-based and inclusive. It corresponds to the position of the first character
+ * which is part of this token. If this character was a unicode escape sequence, it points at the first
+ * character of this sequence.
+ *
+ * @return the starting position of the current token inside the original source
+ */
+ int getCurrentTokenStartPosition();
+
+ /**
+ * Answers the ending position of the current token inside the original source.
+ * This position is zero-based and inclusive. It corresponds to the position of the last character
+ * which is part of this token. If this character was a unicode escape sequence, it points at the last
+ * character of this sequence.
+ *
+ * @return the ending position of the current token inside the original source
+ */
+ int getCurrentTokenEndPosition();
+
+ /**
+ * Answers the starting position of a given line number. This line has to have been encountered
+ * already in the tokenization process (in other words, it cannot be used to compute positions of lines beyond
+ * current token). Once the entire source has been processed, it can be used without any limit.
+ * Line starting positions are zero-based, and start immediately after the previous line separator (if any).
+ *
+ * @param lineNumber the given line number
+ * @return the starting position of a given line number
+ */
+ int getLineStart(int lineNumber);
+
+ /**
+ * Answers the ending position of a given line number. This line has to have been encountered
+ * already in the tokenization process (in other words, it cannot be used to compute positions of lines beyond
+ * current token). Once the entire source has been processed, it can be used without any limit.
+ * Line ending positions are zero-based, and correspond to the last character of the line separator
+ * (in case multi-character line separators).
+ *
+ * @param lineNumber the given line number
+ * @return the ending position of a given line number
+ **/
+ int getLineEnd(int lineNumber);
+
+ /**
+ * Answers an array of the ending positions of the lines encountered so far. Line ending positions
+ * are zero-based, and correspond to the last character of the line separator (in case multi-character
+ * line separators).
+ *
+ * @return an array of the ending positions of the lines encountered so far
+ */
+ int[] getLineEnds();
+
+ /**
+ * Answers a 1-based line number using the lines which have been encountered so far. If the position
+ * is located beyond the current scanned line, then the last line number will be answered.
+ *
+ * @param charPosition the given character position
+ * @return a 1-based line number using the lines which have been encountered so far
+ */
+ int getLineNumber(int charPosition);
+
+ /**
+ * Read the next token in the source, and answers its ID as specified by ITerminalSymbols
.
+ * Note that the actual token ID values are subject to change if new keywords were added to the language
+ * (for instance, 'assert' is a keyword in 1.4).
+ *
+ * @throws InvalidInputException in case a lexical error was detected while reading the current token
+ * @return the next token
+ */
+ int getNextToken() throws InvalidInputException;
+
+ /**
+ * Answers the original source being processed (not a copy of it).
+ *
+ * @return the original source being processed
+ */
+ char[] getSource();
+
+ /**
+ * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
+ * Beyond this position, the scanner will answer EOF tokens (ITerminalSymbols.TokenNameEOF
).
+ *
+ * @param startPosition the given start position
+ * @param endPosition the given end position
+ */
+ void resetTo(int startPosition, int endPosition);
+
+ /**
+ * Set the scanner source to process. By default, the scanner will consider starting at the beginning of the
+ * source until it reaches its end.
+ * If the given source is null
, this clears the source.
+ *
+ * @param source the given source
+ */
+ void setSource(char[] source);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ITerminalSymbols.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ITerminalSymbols.java
new file mode 100644
index 0000000..364a7b4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ITerminalSymbols.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.compiler;
+
+/**
+ * Maps each terminal symbol in the javaScript-grammar into a unique integer.
+ * This integer is used to represent the terminal when computing a parsing action.
+ * + * This interface is not intended to be implemented by clients. + *
+ * + * @see IScanner + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface ITerminalSymbols { + + int TokenNameWHITESPACE = 1000; + int TokenNameCOMMENT_LINE = 1001; + int TokenNameCOMMENT_BLOCK = 1002; + int TokenNameCOMMENT_JAVADOC = 1003; + + int TokenNameIdentifier = 5; + int TokenNameabstract = 98; + + int TokenNameassert = 118; + int TokenNameboolean = 18; + int TokenNamebreak = 119; + int TokenNamebyte = 19; + int TokenNamecase = 211; + int TokenNamecatch = 225; + int TokenNamechar = 20; + int TokenNameclass = 165; + int TokenNamecontinue = 120; + int TokenNamedefault = 212; + int TokenNamedo = 121; + int TokenNamedouble = 21; + int TokenNameelse = 213; + int TokenNameextends = 243; + int TokenNamefalse = 37; + int TokenNamefinal = 99; + int TokenNamefinally = 226; + int TokenNamefloat = 22; + int TokenNamefor = 122; + int TokenNameif = 123; + int TokenNameimplements = 268; + int TokenNameimport = 191; + int TokenNameinstanceof = 65; + int TokenNameint = 23; + int TokenNameinterface = 180; + int TokenNamelong = 24; + int TokenNamenative = 100; + int TokenNamenew = 32; + int TokenNamenull = 38; + int TokenNamepackage = 214; + int TokenNameprivate = 101; + int TokenNameprotected = 102; + int TokenNamepublic = 103; + int TokenNamereturn = 124; + int TokenNameshort = 25; + int TokenNamestatic = 94; + int TokenNamestrictfp = 104; + int TokenNamesuper = 33; + int TokenNameswitch = 125; + int TokenNamesynchronized = 85; + int TokenNamethis = 34; + int TokenNamethrow = 126; + int TokenNamethrows = 227; + int TokenNametransient = 105; + int TokenNametrue = 39; + int TokenNametry = 127; + int TokenNamevoid = 26; + int TokenNamevolatile = 106; + int TokenNamewhile = 117; + int TokenNameIntegerLiteral = 40; + int TokenNameLongLiteral = 41; + int TokenNameFloatingPointLiteral = 42; + int TokenNameDoubleLiteral = 43; + int TokenNameCharacterLiteral = 44; + int TokenNameStringLiteral = 45; + int TokenNameRegExLiteral = 46; + int TokenNamePLUS_PLUS = 1; + int TokenNameMINUS_MINUS = 2; + int TokenNameEQUAL_EQUAL = 35; + int TokenNameLESS_EQUAL = 66; + int TokenNameGREATER_EQUAL = 67; + int TokenNameNOT_EQUAL = 36; + int TokenNameLEFT_SHIFT = 14; + int TokenNameRIGHT_SHIFT = 11; + int TokenNameUNSIGNED_RIGHT_SHIFT = 12; + int TokenNamePLUS_EQUAL = 168; + int TokenNameMINUS_EQUAL = 169; + int TokenNameMULTIPLY_EQUAL = 170; + int TokenNameDIVIDE_EQUAL = 171; + int TokenNameAND_EQUAL = 172; + int TokenNameOR_EQUAL = 173; + int TokenNameXOR_EQUAL = 174; + int TokenNameREMAINDER_EQUAL = 175; + int TokenNameLEFT_SHIFT_EQUAL = 176; + int TokenNameRIGHT_SHIFT_EQUAL = 177; + int TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 178; + int TokenNameOR_OR = 80; + int TokenNameAND_AND = 79; + int TokenNamePLUS = 3; + int TokenNameMINUS = 4; + int TokenNameNOT = 71; + int TokenNameREMAINDER = 9; + int TokenNameXOR = 63; + int TokenNameAND = 62; + int TokenNameMULTIPLY = 8; + int TokenNameOR = 70; + int TokenNameTWIDDLE = 72; + int TokenNameDIVIDE = 10; + int TokenNameGREATER = 68; + int TokenNameLESS = 69; + int TokenNameLPAREN = 7; + int TokenNameRPAREN = 86; + int TokenNameLBRACE = 110; + int TokenNameRBRACE = 95; + int TokenNameLBRACKET = 15; + int TokenNameRBRACKET = 166; + int TokenNameSEMICOLON = 64; + int TokenNameQUESTION = 81; + int TokenNameCOLON = 154; + int TokenNameCOMMA = 90; + int TokenNameDOT = 6; + int TokenNameEQUAL = 167; + int TokenNameEOF = 158; + int TokenNameERROR = 309; + + int TokenNameenum = 400; + + int TokenNameAT = 401; + + int TokenNameELLIPSIS = 402; + + int TokenNameconst = 403; + + int TokenNamegoto = 404; + + int TokenNameNOT_EQUAL_EQUAL=450; + int TokenNameEQUAL_EQUAL_EQUAL=451; + int TokenNamedelete=452; + int TokenNamedebugger=453; + int TokenNameexport=454; + int TokenNamefunction=455; + int TokenNamein=456; + int TokenNameinfinity=457; + int TokenNametypeof=458; + int TokenNameundefined=459; + int TokenNamevar=460; + int TokenNamewith=461; + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/InvalidInputException.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/InvalidInputException.java new file mode 100644 index 0000000..bac98f2 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/InvalidInputException.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.compiler; + +/** + * Exception thrown by a scanner when encountering lexical errors. + *+ * This class is not intended to be instantiated or subclassed by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class InvalidInputException extends Exception { + + private static final long serialVersionUID = 2909732853499731592L; // backward compatible + +/** + * Creates a new exception with no detail message. + */ +public InvalidInputException() { + super(); +} + +/** + * Creates a new exception with the given detail message. + * @param message the detail message + */ +public InvalidInputException(String message) { + super(message); +} +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ReconcileContext.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ReconcileContext.java new file mode 100644 index 0000000..fe4ef07 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ReconcileContext.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * mkaufman@bea.com - initial API and implementation + * IBM - renamed from PreReconcileCompilationResult to ReconcileContext + * IBM - rewrote spec + * + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.compiler; + +import java.util.HashMap; + +import org.eclipse.wst.jsdt.core.IJavaScriptUnit; +import org.eclipse.wst.jsdt.core.IJavaScriptElementDelta; +import org.eclipse.wst.jsdt.core.IJavaScriptModelMarker; +import org.eclipse.wst.jsdt.core.JavaScriptModelException; +import org.eclipse.wst.jsdt.core.dom.AST; +import org.eclipse.wst.jsdt.core.dom.ASTParser; +import org.eclipse.wst.jsdt.internal.core.CompilationUnit; +import org.eclipse.wst.jsdt.internal.core.JavaProject; +import org.eclipse.wst.jsdt.internal.core.ReconcileWorkingCopyOperation; + +/** + * The context of a reconcile event that is notified to interested validation + * participants while a reconcile operation is running. + *+ * A reconcile participant can get the AST for the reconcile-operation using + * {@link #getAST3()}. If the participant modifies in any way the AST + * (either by modifying the source of the working copy, or modifying another entity + * that would result in different bindings for the AST), it is expected to reset the + * AST in the context using {@link #resetAST()}. + *
+ * A reconcile participant can also create and return problems using + * {@link #putProblems(String, CategorizedProblem[])}. These problems are then reported + * to the problem requestor of the reconcile operation. + *
+ * This class is not intended to be instanciated or subclassed by clients. + *
+ * + * @see ValidationParticipant#reconcile(ReconcileContext) + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class ReconcileContext { + + private ReconcileWorkingCopyOperation operation; + private CompilationUnit workingCopy; + +/** + * Creates a reconcile context for the given reconcile operation. + *+ * This constructor is not intended to be called by clients. + *
+ * + * @param operation the reconcile operation + */ +public ReconcileContext(ReconcileWorkingCopyOperation operation, CompilationUnit workingCopy) { + this.operation = operation; + this.workingCopy = workingCopy; +} + +/** + * Returns a resolved AST with {@link AST#JLS3 JLS3} level. + * It is created from the current state of the working copy. + * Creates one if none exists yet. + * Returnsnull
if the current state of the working copy
+ * doesn't allow the AST to be created (e.g. if the working copy's content
+ * cannot be parsed).
+ * + * If the AST level requested during reconciling is not {@link AST#JLS3} + * or if binding resolutions was not requested, then a different AST is created. + * Note that this AST does not become the current AST and it is only valid for + * the requestor. + *
+ * + * @return the AST created from the current state of the working copy, + * ornull
if none could be created
+ * @exception JavaScriptModelException if the contents of the working copy
+ * cannot be accessed. Reasons include:
+ * null
if there is no change.
+ * Note that the delta's AST is not yet positioned at this stage. Use {@link #getAST3()}
+ * to get the current AST.
+ *
+ * @return the delta describing the change, or null
if none
+ */
+public IJavaScriptElementDelta getDelta() {
+ return this.operation.deltaBuilder.delta;
+}
+
+/**
+ * Returns the problems to be reported to the problem requester of the reconcile operation
+ * for the given marker type.
+ * Returns null
if no problems need to be reported for this marker type.
+ *
+ * @param markerType the given marker type
+ * @return problems to be reported to the problem requester
+ */
+public CategorizedProblem[] getProblems(String markerType) {
+ if (this.operation.problems == null) return null;
+ return (CategorizedProblem[]) this.operation.problems.get(markerType);
+}
+
+/**
+ * Returns the working copy this context refers to.
+ *
+ * @return the working copy this context refers to
+ */
+public IJavaScriptUnit getWorkingCopy() {
+ return this.workingCopy;
+}
+
+/**
+ * Resets the AST carried by this context.
+ * A validation participant that modifies the environment that would result in different
+ * bindings for the AST is expected to reset the AST on this context, so that other
+ * participants don't get a stale AST.
+ * + * Note that resetting the AST will not restart the reconcile process. Only further + * participants will see the new AST. Thus participants running before the one that + * resets the AST will have a stale view of the AST and its problems. Use + * the validation participant extension point to order the participants. + *
+ */ +public void resetAST() { + this.operation.ast = null; + putProblems(IJavaScriptModelMarker.JAVASCRIPT_MODEL_PROBLEM_MARKER, null); + putProblems(IJavaScriptModelMarker.TASK_MARKER, null); +} + +/** + * Sets the problems to be reported to the problem requester of the reconcile operation + * for the given marker type. + *null
indicates that no problems need to be reported.
+ * + * Using this functionality, a participant that resolves problems for a given marker type + * can hide those problems since they don't exist any longer. + *
+ * + * @param markerType the marker type of the given problems + * @param problems the problems to be reported to the problem requester of the reconcile operation, + * ornull
if none
+ */
+public void putProblems(String markerType, CategorizedProblem[] problems) {
+ if (this.operation.problems == null)
+ this.operation.problems = new HashMap();
+ this.operation.problems.put(markerType, problems);
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ValidationParticipant.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ValidationParticipant.java
new file mode 100644
index 0000000..9360a70
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/ValidationParticipant.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * mkaufman@bea.com - initial API as IvalidationParticipant
+ * IBM - changed from interface IvalidationParticipant to abstract class validationParticipant
+ * IBM - rewrote spec
+ *
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.compiler;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+
+/**
+ * A validation participant is notified of events occuring during the validation process.
+ * The notified events are the result of a build action, a clean action, a reconcile operation
+ * (for a working copy), etc.
+ * + * Clients wishing to participate in the validation process must subclass this class, and implement + * {@link #isActive(IJavaScriptProject)}, {@link #aboutToBuild(IJavaScriptProject)}, + * {@link #reconcile(ReconcileContext)}, etc. +*
+ * This class is intended to be subclassed by clients. + *
+ * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public abstract class ValidationParticipant { + +public static int READY_FOR_BUILD = 1; +public static int NEEDS_FULL_BUILD = 2; + +/** + * Notifies this participant that a validation is about to start and provides it the opportunity to + * create missing source folders for generated source files. Additional source folders + * should be marked as optional so the project can be built when the folders do not exist. + * Only sent to participants interested in the project. + *
+ * Default is to return READY_FOR_BUILD
.
+ *
+ * Default is to return false
.
+ *
+ * For efficiency, participants that are not interested in the
+ * given project should return false
for that project.
+ *
+ * Note that a participant should not modify the buffer of the working copy that is being reconciled. + *
+ * Default is to do nothing. + *
+ * @param context the reconcile context to act on + */ +public void reconcile(ReconcileContext context) { + // do nothing by default +} + +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/libraries/LibraryLocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/libraries/LibraryLocation.java new file mode 100644 index 0000000..0c8ad26 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/libraries/LibraryLocation.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2005, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core.compiler.libraries; + +import org.eclipse.core.runtime.IPath; +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public interface LibraryLocation { + + /** + * @param name + * @return path to the given library name + */ + public String getLibraryPath(String name); + + /** + * @return a list of files in the library + */ + public char[][] getLibraryFileNames(); + + /** + * @return relative path within the plugin library files are stored + */ + public IPath getLibraryPathInPlugin(); + + /** + * @return working location to store library files. + */ + public IPath getWorkingLibPath(); + + /** + * @param name + * @return path to the given library name + */ + public String getLibraryPath(char[] name); +} \ No newline at end of file diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/libraries/SystemLibraryLocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/libraries/SystemLibraryLocation.java new file mode 100644 index 0000000..9d87517 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/compiler/libraries/SystemLibraryLocation.java @@ -0,0 +1,212 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.jsdt.core.compiler.libraries; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.wst.jsdt.core.JavaScriptCore; +import org.eclipse.wst.jsdt.internal.core.util.Util; +/** + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public class SystemLibraryLocation implements LibraryLocation { + + public static final char[] SYSTEM_LIBARAY_NAME= {'s','y','s','t','e','m','.','j','s'}; + public static final char[] LIBRARY_RUNTIME_DIRECTORY={'l','i','b','r','a','r','i','e','s'}; + public static final char[] LIBRARY_PLUGIN_DIRECTORY={'l','i','b','r','a','r','i','e','s'}; + private static final boolean AUTO_UPDATE_LIBS=true; + + private static SystemLibraryLocation fInstance; + + public static LibraryLocation getInstance() { + if(fInstance==null) + fInstance = new SystemLibraryLocation(); + return fInstance; + } + + public IPath getLibraryPathInPlugin() { + return new Path("libraries"); //$NON-NLS-1$ + } + + public char[][] getLibraryFileNames() { + return new char[][] {SYSTEM_LIBARAY_NAME}; + } + + protected String getPluginId() { + return JavaScriptCore.PLUGIN_ID; + } + + public char[][] getAllFilesInPluginDirectory(String directory){ + Enumeration entries = (Platform.getBundle(getPluginId()).getEntryPaths(directory)); + List allEntries = new ArrayList(); + while (entries.hasMoreElements()) { + Path value = new Path((String) entries.nextElement()); + char[] filename = value.lastSegment().toCharArray(); + if (Util.isJavaLikeFileName(filename)) { //$NON-NLS-1$ + allEntries.add(filename); + } + } + char[][] fileNames = new char[allEntries.size()][]; + + for (int i = 0; i < allEntries.size(); i++) { + fileNames[i] = (char[]) allEntries.get(i); + } + + return fileNames; + } + + public SystemLibraryLocation() { + super(); + + IPath libraryRuntimePath = Platform.getStateLocation(Platform.getBundle(JavaScriptCore.PLUGIN_ID)).append(new String(LIBRARY_RUNTIME_DIRECTORY)); + try { + if (!libraryRuntimePath.toFile().exists()) { + libraryRuntimePath.toFile().mkdir(); + } + } + catch (SecurityException e) { + Platform.getLog(Platform.getBundle(JavaScriptCore.PLUGIN_ID)).log(new Status(IStatus.ERROR, JavaScriptCore.PLUGIN_ID, "Problem creating folder " + libraryRuntimePath, e));//$NON-NLS-1$ + } + + char[][] libFiles = getLibraryFileNames(); + + for (int i = 0; i < libFiles.length; i++) { + IPath workingLibLocation = libraryRuntimePath.addTrailingSeparator().append(new String(libFiles[i])); + File library = workingLibLocation.toFile(); + + if (!library.exists()) { + InputStream is = null; + try { + is = FileLocator.openStream(Platform.getBundle(getPluginId()), getLibraryPathInPlugin().append(new String(libFiles[i])), false); + } + catch (IOException e) { + Platform.getLog(Platform.getBundle(getPluginId())).log(new Status(IStatus.ERROR, getPluginId(), "Could not read " + getPluginId() + ":" + getLibraryPathInPlugin().append(new String(libFiles[i])), e));//$NON-NLS-1$ //$NON-NLS-2$ + } + if (is != null) { + try { + copyFile(is, library); + } + catch (IOException e) { + Platform.getLog(Platform.getBundle(getPluginId())).log(new Status(IStatus.ERROR, getPluginId(), "Problem writing to " + workingLibLocation, e));//$NON-NLS-1$ + } + } + } + else if (AUTO_UPDATE_LIBS) { + long lastModold = library.lastModified(); + URL path = null; + URL entry = null; + try { + entry = Platform.getBundle(getPluginId()).getEntry(getLibraryPathInPlugin().append(new String(libFiles[i])).toString()); + path = FileLocator.toFileURL(entry); + } + catch (IOException e) { + // URL conversion error + Platform.getLog(Platform.getBundle(JavaScriptCore.PLUGIN_ID)).log(new Status(IStatus.ERROR, getPluginId(), "Problem getting file path from " + entry, e));//$NON-NLS-1$ + } + catch (IllegalStateException e) { + // bundle uninstalled, not really bad? + } + + if (path != null) { + File inPlugin = new File(path.getFile()); + long lastModNew = inPlugin.lastModified(); + if (lastModNew > lastModold) { + InputStream is = null; + try { + is = FileLocator.openStream(Platform.getBundle(getPluginId()), getLibraryPathInPlugin().append(new String(libFiles[i])), false); + } + catch (IOException e) { + Platform.getLog(Platform.getBundle(getPluginId())).log(new Status(IStatus.ERROR, getPluginId(), "Could not read " + getPluginId() + ":" + getLibraryPathInPlugin().append(new String(libFiles[i])), e));//$NON-NLS-1$ //$NON-NLS-2$ + } + + if (is != null) { + // Updating old library file + library.delete(); + + try { + copyFile(is, library); + } + catch (IOException e) { + Platform.getLog(Platform.getBundle(getPluginId())).log(new Status(IStatus.ERROR, getPluginId(), "Problem writing to " + library, e));//$NON-NLS-1$ + } + } + } + } + } + } + } + + + public IPath getWorkingLibPath() { + return new Path(getLibraryPath("")); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.wst.jsdt.core.compiler.libraries.LibraryLocation#getLibraryPath(java.lang.String) + */ + public String getLibraryPath(String name){ + return JavaScriptCore.getPlugin().getStateLocation().append( new String(LIBRARY_RUNTIME_DIRECTORY) ).addTrailingSeparator().append(name).toString(); + } + + public String getLibraryPath(char[] name){ + return getLibraryPath(new String(name)); + + } + protected static void copyFile(InputStream src, File dst) throws IOException { + InputStream in = null; + OutputStream out = null; + try { + in = new BufferedInputStream(src); + out = new BufferedOutputStream(new FileOutputStream(dst)); + byte[] buffer = new byte[4096]; + int len; + while ((len = in.read(buffer)) != -1) { + out.write(buffer, 0, len); + } + } + finally { + if (in != null) + try { + in.close(); + } + catch (IOException e) { + // problem closing, no recovery or diagnosis possible + } + if (out != null) + try { + out.close(); + } + catch (IOException e) { + // problem closing, no recovery or diagnosis possible + } + } + } +} diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AST.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AST.java new file mode 100644 index 0000000..4c8c9e6 --- /dev/null +++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AST.java @@ -0,0 +1,2372 @@ +/******************************************************************************* + * Copyright (c) 2000, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.wst.jsdt.core.dom; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.IDocument; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.wst.jsdt.core.IJavaScriptUnit; +import org.eclipse.wst.jsdt.core.JavaScriptCore; +import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner; + +/** + * Umbrella owner and abstract syntax tree node factory. + * AnAST
instance serves as the common owner of any number of
+ * AST nodes, and as the factory for creating new AST nodes owned by that
+ * instance.
+ *
+ * Abstract syntax trees may be hand constructed by clients, using the
+ * newTYPE
factory methods to create new nodes, and the
+ * various setCHILD
methods
+ * (see {@link org.eclipse.wst.jsdt.core.dom.ASTNode ASTNode} and its subclasses)
+ * to connect them together.
+ *
+ * Each AST node belongs to a unique AST instance, called the owning AST. + * The children of an AST node always have the same owner as their parent node. + * If a node from one AST is to be added to a different AST, the subtree must + * be cloned first to ensures that the added nodes have the correct owning AST. + *
+ *
+ * There can be any number of AST nodes owned by a single AST instance that are
+ * unparented. Each of these nodes is the root of a separate little tree of nodes.
+ * The method ASTNode.getRoot()
navigates from any node to the root
+ * of the tree that it is contained in. Ordinarily, an AST instance has one main
+ * tree (rooted at a JavaScriptUnit
), with newly-created nodes appearing
+ * as additional roots until they are parented somewhere under the main tree.
+ * One can navigate from any node to its AST instance, but not conversely.
+ *
+ * The class {@link ASTParser} parses a string + * containing a JavaScript source code and returns an abstract syntax tree + * for it. The resulting nodes carry source ranges relating the node back to + * the original source characters. + *
+ *
+ * JavaScript units created by ASTParser
from a
+ * source document can be serialized after arbitrary modifications
+ * with minimal loss of original formatting. Here is an example:
+ *
+ * Document doc = new Document("var abc;\nfunction X() {}\n"); + * ASTParser parser = ASTParser.newParser(AST.JLS3); + * parser.setSource(doc.get().toCharArray()); + * JavaScriptUnit cu = (JavaScriptUnit) parser.createAST(null); + * cu.recordModifications(); + * AST ast = cu.getAST(); + * FunctionDeclaration id = ast.newFunctionDeclaration(); + * id.setName(ast.newName("X2"); + * cu.statements().add(id); // add declaration at end + * TextEdit edits = cu.rewrite(document, null); + * UndoEdit undo = edits.apply(document); + *+ * See also {@link org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite} for + * an alternative way to describe and serialize changes to a + * read-only AST. + * + *
+ * Clients may create instances of this class using {@link #newAST(int)}, + * but this class is not intended to be subclassed. + *
+ * + * @see ASTParser + * @see ASTNode + * + * Provisional API: This class/interface is part of an interim API that is still under development and expected to + * change significantly before reaching stability. It is being made available at this early stage to solicit feedback + * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken + * (repeatedly) as the API evolves. + */ +public final class AST { + /** + * Constant for indicating the AST API that handles standard Javascript. + * This API is capable of handling all constructs + * in the JavaScript language as described in the ECMA-262 + * Specification. + * + * @deprecated Clients should use the {@link #JLS3} AST API instead. + */ + public static final int JLS2 = 2; + + /** + * Internal synonym for {@link #JLS2}. Use to alleviate + * deprecation warnings. + */ + /*package*/ static final int JLS2_INTERNAL = JLS2; + + /** + * Constant for indicating the AST API that handles ECMAScript 4. + * This API is capable of handling all constructs in the + * JavaScript language as described in the ECMAScript 4 + * Specification. + * ECMAScript 4 is a superset of all earlier versions of the + * JavaScript language. + * + */ + public static final int JLS3 = 3; + + /** + * The binding resolver for this AST. Initially a binding resolver that + * does not resolve names at all. + */ + private BindingResolver resolver = new BindingResolver(); + + /** + * The event handler for this AST. + * Initially an event handler that does not nothing. + */ + private NodeEventHandler eventHandler = new NodeEventHandler(); + + /** + * Level of AST API supported by this AST. + */ + int apiLevel; + + /** + * Internal modification count; initially 0; increases monotonically + * by one or more as the AST is successively modified. + */ + private long modificationCount = 0; + + /** + * Internal original modification count; value is equals to
+ * modificationCount
at the end of the parse (ASTParser
+ *
). If this ast is not created with a parser then value is 0.
+ */
+ private long originalModificationCount = 0;
+
+ /**
+ * When disableEvents > 0, events are not reported and
+ * the modification count stays fixed.
+ * + * This mechanism is used in lazy initialization of a node + * to prevent events from being reported for the modification + * of the node as well as for the creation of the missing child. + *
+ */ + private int disableEvents = 0; + + /** + * Internal object unique to the AST instance. Readers must synchronize on + * this object when the modifying instance fields. + */ + private final Object internalASTLock = new Object(); + + /** + * JavaScript Scanner used to validate preconditions for the creation of specific nodes + * like CharacterLiteral, NumberLiteral, StringLiteral or SimpleName. + */ + Scanner scanner; + + /** + * Internal ast rewriter used to record ast modification when record mode is enabled. + */ + InternalASTRewrite rewriter; + + /** + * Default value offlag when a new node is created.
+ */
+ private int defaultNodeFlag = 0;
+
+ /**
+ * Creates a new JavaScript abstract syntax tree
+ * (AST) following the specified set of API rules.
+ *
+ * @param level the API level; one of the LEVEL constants
+ */
+ private AST(int level) {
+ if ((level != AST.JLS2)
+ && (level != AST.JLS3)) {
+ throw new IllegalArgumentException();
+ }
+ this.apiLevel = level;
+ // initialize a scanner
+ this.scanner = new Scanner(
+ true /*comment*/,
+ true /*whitespace*/,
+ false /*nls*/,
+ ClassFileConstants.JDK1_3 /*sourceLevel*/,
+ ClassFileConstants.JDK1_5 /*complianceLevel*/,
+ null/*taskTag*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ }
+
+ /**
+ * Creates a new, empty abstract syntax tree using default options.
+ *
+ * @see JavaScriptCore#getDefaultOptions()
+ * @deprecated Clients should port their code to use the new JLS3 AST API and call
+ * {@link #newAST(int) AST.newAST(AST.JLS3)} instead of using this constructor.
+ */
+ public AST() {
+ this(JavaScriptCore.getDefaultOptions());
+ }
+
+ /**
+ * Internal method.
+ *
+ * This method converts the given internal compiler AST for the given source string
+ * into a javaScript unit. This method is not intended to be called by clients.
+ *
+ *
+ * @param level the API level; one of the LEVEL constants
+ * @param compilationUnitDeclaration an internal AST node for a javaScript unit declaration
+ * @param source the string of the JavaScript javaScript unit
+ * @param options validator options
+ * @param workingCopy the working copy that the AST is created from
+ * @param monitor the progress monitor used to report progress and request cancelation,
+ * or null
if none
+ * @param isResolved whether the given javaScript unit declaration is resolved
+ * @return the javaScript unit node
+ */
+ public static JavaScriptUnit convertCompilationUnit(
+ int level,
+ org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration,
+ char[] source,
+ Map options,
+ boolean isResolved,
+ org.eclipse.wst.jsdt.internal.core.CompilationUnit workingCopy,
+ int reconcileFlags,
+ IProgressMonitor monitor) {
+
+ ASTConverter converter = new ASTConverter(options, isResolved, monitor);
+ AST ast = AST.newAST(level);
+ int savedDefaultNodeFlag = ast.getDefaultNodeFlag();
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ BindingResolver resolver = null;
+ if (isResolved) {
+ resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, workingCopy.owner, new DefaultBindingResolver.BindingTables(), false);
+ ast.setFlag(AST.RESOLVED_BINDINGS);
+ } else {
+ resolver = new BindingResolver();
+ }
+ ast.setFlag(reconcileFlags);
+ ast.setBindingResolver(resolver);
+ converter.setAST(ast);
+
+ JavaScriptUnit unit = converter.convert(compilationUnitDeclaration, source);
+ unit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
+ unit.setTypeRoot(workingCopy);
+ ast.setDefaultNodeFlag(savedDefaultNodeFlag);
+ return unit;
+ }
+
+ /**
+ * Creates a new, empty abstract syntax tree using the given options.
+ *
+ * @param options the table of options (key type: String
;
+ * value type: String
)
+ * @see JavaScriptCore#getDefaultOptions()
+ * @deprecated Clients should port their code to use the new JLS3 AST API and call
+ * {@link #newAST(int) AST.newAST(AST.JLS3)} instead of using this constructor.
+ */
+ public AST(Map options) {
+ this(JLS2);
+ Object sourceLevelOption = options.get(JavaScriptCore.COMPILER_SOURCE);
+ long sourceLevel = ClassFileConstants.JDK1_3;
+ if (JavaScriptCore.VERSION_1_4.equals(sourceLevelOption)) {
+ sourceLevel = ClassFileConstants.JDK1_4;
+ } else if (JavaScriptCore.VERSION_1_5.equals(sourceLevelOption)) {
+ sourceLevel = ClassFileConstants.JDK1_5;
+ }
+ Object complianceLevelOption = options.get(JavaScriptCore.COMPILER_COMPLIANCE);
+ long complianceLevel = ClassFileConstants.JDK1_3;
+ if (JavaScriptCore.VERSION_1_4.equals(complianceLevelOption)) {
+ complianceLevel = ClassFileConstants.JDK1_4;
+ } else if (JavaScriptCore.VERSION_1_5.equals(complianceLevelOption)) {
+ complianceLevel = ClassFileConstants.JDK1_5;
+ }
+ // override scanner if 1.4 or 1.5 asked for
+ this.scanner = new Scanner(
+ true /*comment*/,
+ true /*whitespace*/,
+ false /*nls*/,
+ sourceLevel /*sourceLevel*/,
+ complianceLevel /*complianceLevel*/,
+ null/*taskTag*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ }
+
+ /**
+ * Creates a new JavaScript abstract syntax tree
+ * (AST) following the specified set of API rules.
+ *
+ * @param level the API level; one of the LEVEL constants
+ * @return new AST instance following the specified set of API rules.
+ * @exception IllegalArgumentException if:
+ *
+ * - the API level is not one of the LEVEL constants
+ *
+ */
+ public static AST newAST(int level) {
+ if ((level != AST.JLS2)
+ && (level != AST.JLS3)) {
+ throw new IllegalArgumentException();
+ }
+ return new AST(level);
+ }
+
+ /**
+ * Returns the modification count for this AST. The modification count
+ * is a non-negative value that increases (by 1 or perhaps by more) as
+ * this AST or its nodes are changed. The initial value is unspecified.
+ *
+ * The following things count as modifying an AST:
+ *
+ * - creating a new node owned by this AST,
+ * - adding a child to a node owned by this AST,
+ * - removing a child from a node owned by this AST,
+ * - setting a non-node attribute of a node owned by this AST.
+ *
+ *
+ * Operations which do not entail creating or modifying existing nodes
+ * do not increase the modification count.
+ *
+ * N.B. This method may be called several times in the course
+ * of a single client operation. The only promise is that the modification
+ * count increases monotonically as the AST or its nodes change; there is
+ * no promise that a modifying operation increases the count by exactly 1.
+ *
+ *
+ * @return the current value (non-negative) of the modification counter of
+ * this AST
+ */
+ public long modificationCount() {
+ return this.modificationCount;
+ }
+
+ /**
+ * Return the API level supported by this AST.
+ *
+ * @return level the API level; one of the JLS*
LEVEL
+ * declared on AST
; assume this set is open-ended
+ */
+ public int apiLevel() {
+ return this.apiLevel;
+ }
+
+ /**
+ * Indicates that this AST is about to be modified.
+ *
+ * The following things count as modifying an AST:
+ *
+ * - creating a new node owned by this AST
+ * - adding a child to a node owned by this AST
+ * - removing a child from a node owned by this AST
+ * - setting a non-node attribute of a node owned by this AST
.
+ *
+ *
+ *
+ * N.B. This method may be called several times in the course
+ * of a single client operation.
+ *
+ */
+ void modifying() {
+ // when this method is called during lazy init, events are disabled
+ // and the modification count will not be increased
+ if (this.disableEvents > 0) {
+ return;
+ }
+ // increase the modification count
+ this.modificationCount++;
+ }
+
+ /**
+ * Disable events.
+ * This method is thread-safe for AST readers.
+ *
+ * @see #reenableEvents()
+ */
+ final void disableEvents() {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by another reader
+ this.disableEvents++;
+ }
+ // while disableEvents > 0 no events will be reported, and mod count will stay fixed
+ }
+
+ /**
+ * Reenable events.
+ * This method is thread-safe for AST readers.
+ *
+ * @see #disableEvents()
+ */
+ final void reenableEvents() {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by another reader
+ this.disableEvents--;
+ }
+ }
+
+ /**
+ * Reports that the given node is about to lose a child.
+ *
+ * @param node the node about to be modified
+ * @param child the node about to be removed
+ * @param property the child or child list property descriptor
+ */
+ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE DEL]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preRemoveChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node just lost a child.
+ *
+ * @param node the node that was modified
+ * @param child the child node that was removed
+ * @param property the child or child list property descriptor
+ */
+ void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE DEL]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postRemoveChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about have a child replaced.
+ *
+ * @param node the node about to be modified
+ * @param child the child node about to be removed
+ * @param newChild the replacement child
+ * @param property the child or child list property descriptor
+ */
+ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE REP]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preReplaceChildEvent(node, child, newChild, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just had a child replaced.
+ *
+ * @param node the node modified
+ * @param child the child removed
+ * @param newChild the replacement child
+ * @param property the child or child list property descriptor
+ */
+ void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE REP]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postReplaceChildEvent(node, child, newChild, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has not been changed yet
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about to gain a child.
+ *
+ * @param node the node that to be modified
+ * @param child the node that to be added as a child
+ * @param property the child or child list property descriptor
+ */
+ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE ADD]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preAddChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just gained a child.
+ *
+ * @param node the node that was modified
+ * @param child the node that was added as a child
+ * @param property the child or child list property descriptor
+ */
+ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE ADD]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postAddChildEvent(node, child, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about to change the value of a
+ * non-child property.
+ *
+ * @param node the node to be modified
+ * @param property the property descriptor
+ */
+ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CHANGE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preValueChangeEvent(node, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just changed the value of a
+ * non-child property.
+ *
+ * @param node the node that was modified
+ * @param property the property descriptor
+ */
+ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers during lazy init
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CHANGE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postValueChangeEvent(node, property);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node is about to be cloned.
+ *
+ * @param node the node to be cloned
+ */
+ void preCloneNodeEvent(ASTNode node) {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CLONE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.preCloneNodeEvent(node);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Reports that the given node has just been cloned.
+ *
+ * @param node the node that was cloned
+ * @param clone the clone of node
+ */
+ void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+ synchronized (this.internalASTLock) {
+ // guard against concurrent access by a reader doing lazy init
+ if (this.disableEvents > 0) {
+ // doing lazy init OR already processing an event
+ // System.out.println("[BOUNCE CLONE]");
+ return;
+ } else {
+ disableEvents();
+ }
+ }
+ try {
+ this.eventHandler.postCloneNodeEvent(node, clone);
+ // N.B. even if event handler blows up, the AST is not
+ // corrupted since node has already been changed
+ } finally {
+ reenableEvents();
+ }
+ }
+
+ /**
+ * Returns the binding resolver for this AST.
+ *
+ * @return the binding resolver for this AST
+ */
+ BindingResolver getBindingResolver() {
+ return this.resolver;
+ }
+
+ /**
+ * Returns the event handler for this AST.
+ *
+ * @return the event handler for this AST
+ */
+ NodeEventHandler getEventHandler() {
+ return this.eventHandler;
+ }
+
+ /**
+ * Sets the event handler for this AST.
+ *
+ * @param eventHandler the event handler for this AST
+ */
+ void setEventHandler(NodeEventHandler eventHandler) {
+ if (this.eventHandler == null) {
+ throw new IllegalArgumentException();
+ }
+ this.eventHandler = eventHandler;
+ }
+
+ /**
+ * Returns default node flags of new nodes of this AST.
+ *
+ * @return the default node flags of new nodes of this AST
+ */
+ int getDefaultNodeFlag() {
+ return this.defaultNodeFlag;
+ }
+
+ /**
+ * Sets default node flags of new nodes of this AST.
+ *
+ * @param flag node flags of new nodes of this AST
+ */
+ void setDefaultNodeFlag(int flag) {
+ this.defaultNodeFlag = flag;
+ }
+
+ /**
+ * Set originalModificationCount
to the current modification count
+ *
+ */
+ void setOriginalModificationCount(long count) {
+ this.originalModificationCount = count;
+ }
+
+ /**
+ * Returns the type binding for a "well known" type.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @param name the name of a well known type
+ * @return the corresponding type binding, or null
if the
+ * named type is not considered well known or if no binding can be found
+ * for it
+ */
+ public ITypeBinding resolveWellKnownType(String name) {
+ if (name == null) {
+ return null;
+ }
+ return getBindingResolver().resolveWellKnownType(name);
+ }
+
+ /**
+ * Sets the binding resolver for this AST.
+ *
+ * @param resolver the new binding resolver for this AST
+ */
+ void setBindingResolver(BindingResolver resolver) {
+ if (resolver == null) {
+ throw new IllegalArgumentException();
+ }
+ this.resolver = resolver;
+ }
+
+ /**
+ * Checks that this AST operation is not used when
+ * building level JLS2 ASTs.
+
+ * @exception UnsupportedOperationException
+ */
+ void unsupportedIn2() {
+ if (this.apiLevel == AST.JLS2) {
+ throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Checks that this AST operation is only used when
+ * building level JLS2 ASTs.
+
+ * @exception UnsupportedOperationException
+ */
+ void supportedOnlyIn2() {
+ if (this.apiLevel != AST.JLS2) {
+ throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * new Class[] {AST.class}
+ */
+ private static final Class[] AST_CLASS = new Class[] {AST.class};
+
+ /**
+ * new Object[] {this}
+ */
+ private final Object[] THIS_AST= new Object[] {this};
+
+ /*
+ * Must not collide with a value for IJavaScriptUnit constants
+ */
+ static final int RESOLVED_BINDINGS = 0x80000000;
+
+ /**
+ * Tag bit value. This represents internal state of the tree.
+ */
+ private int bits;
+
+ /**
+ * Creates an unparented node of the given node class
+ * (non-abstract subclass of {@link ASTNode}).
+ *
+ * @param nodeClass AST node class
+ * @return a new unparented node owned by this AST
+ * @exception IllegalArgumentException if nodeClass
is
+ * null
or is not a concrete node type class
+ */
+ public ASTNode createInstance(Class nodeClass) {
+ if (nodeClass == null) {
+ throw new IllegalArgumentException();
+ }
+ try {
+ // invoke constructor with signature Foo(AST)
+ Constructor c = nodeClass.getDeclaredConstructor(AST_CLASS);
+ Object result = c.newInstance(this.THIS_AST);
+ return (ASTNode) result;
+ } catch (NoSuchMethodException e) {
+ // all AST node classes have a Foo(AST) constructor
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ } catch (InstantiationException e) {
+ // all concrete AST node classes can be instantiated
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ } catch (IllegalAccessException e) {
+ // all AST node classes have an accessible Foo(AST) constructor
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ } catch (InvocationTargetException e) {
+ // concrete AST node classes do not die in the constructor
+ // therefore nodeClass is not legit
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Creates an unparented node of the given node type.
+ * This convenience method is equivalent to:
+ *
+ * createInstance(ASTNode.nodeClassForType(nodeType))
+ *
+ *
+ * @param nodeType AST node type, one of the node type
+ * constants declared on {@link ASTNode}
+ * @return a new unparented node owned by this AST
+ * @exception IllegalArgumentException if nodeType
is
+ * not a legal AST node type
+ */
+ public ASTNode createInstance(int nodeType) {
+ // nodeClassForType throws IllegalArgumentException if nodeType is bogus
+ Class nodeClass = ASTNode.nodeClassForType(nodeType);
+ return createInstance(nodeClass);
+ }
+
+ //=============================== NAMES ===========================
+ /**
+ * Creates and returns a new unparented simple name node for the given
+ * identifier. The identifier should be a legal JavaScript identifier, but not
+ * a keyword, boolean literal ("true", "false") or null literal ("null").
+ *
+ * @param identifier the identifier
+ * @return a new unparented simple name node
+ * @exception IllegalArgumentException if the identifier is invalid
+ */
+ public SimpleName newSimpleName(String identifier) {
+ if (identifier == null) {
+ throw new IllegalArgumentException();
+ }
+ SimpleName result = new SimpleName(this);
+ result.setIdentifier(identifier);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented qualified name node for the given
+ * qualifier and simple name child node.
+ *
+ * @param qualifier the qualifier name node
+ * @param name the simple name being qualified
+ * @return a new unparented qualified name node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public QualifiedName newQualifiedName(
+ Name qualifier,
+ SimpleName name) {
+ QualifiedName result = new QualifiedName(this);
+ result.setQualifier(qualifier);
+ result.setName(name);
+ return result;
+
+ }
+
+ /**
+ * Creates and returns a new unparented name node for the given name
+ * segments. Returns a simple name if there is only one name segment, and
+ * a qualified name if there are multiple name segments. Each of the name
+ * segments should be legal JavaScript identifiers (this constraint may or may
+ * not be enforced), and there must be at least one name segment.
+ *
+ * @param identifiers a list of 1 or more name segments, each of which
+ * is a legal JavaScript identifier
+ * @return a new unparented name node
+ * @exception IllegalArgumentException if:
+ *
+ * - the identifier is invalid
+ * - the list of identifiers is empty
+ *
+ */
+ public Name newName(String[] identifiers) {
+ // update internalSetName(String[] if changed
+ int count = identifiers.length;
+ if (count == 0) {
+ throw new IllegalArgumentException();
+ }
+ Name result = newSimpleName(identifiers[0]);
+ for (int i = 1; i < count; i++) {
+ SimpleName name = newSimpleName(identifiers[i]);
+ result = newQualifiedName(result, name);
+ }
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * This method is a copy of setName(String[]) that doesn't do any validation.
+ */
+ Name internalNewName(String[] identifiers) {
+ int count = identifiers.length;
+ if (count == 0) {
+ throw new IllegalArgumentException();
+ }
+ final SimpleName simpleName = new SimpleName(this);
+ simpleName.internalSetIdentifier(identifiers[0]);
+ Name result = simpleName;
+ for (int i = 1; i < count; i++) {
+ SimpleName name = new SimpleName(this);
+ name.internalSetIdentifier(identifiers[i]);
+ result = newQualifiedName(result, name);
+ }
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented name node for the given name.
+ * The name string must consist of 1 or more name segments separated
+ * by single dots '.'. Returns a {@link QualifiedName} if the name has
+ * dots, and a {@link SimpleName} otherwise. Each of the name
+ * segments should be legal JavaScript identifiers (this constraint may or may
+ * not be enforced), and there must be at least one name segment.
+ * The string must not contains white space, '<', '>',
+ * '[', ']', or other any other characters that are not
+ * part of the JavaScript identifiers or separating '.'s.
+ *
+ * @param qualifiedName string consisting of 1 or more name segments,
+ * each of which is a legal JavaScript identifier, separated by single dots '.'
+ * @return a new unparented name node
+ * @exception IllegalArgumentException if:
+ *
+ * - the string is empty
+ * - the string begins or ends in a '.'
+ * - the string has adjacent '.'s
+ * - the segments between the '.'s are not valid JavaScript identifiers
+ *
+ */
+ public Name newName(String qualifiedName) {
+ StringTokenizer t = new StringTokenizer(qualifiedName, ".", true); //$NON-NLS-1$
+ Name result = null;
+ // balance is # of name tokens - # of period tokens seen so far
+ // initially 0; finally 1; should never drop < 0 or > 1
+ int balance = 0;
+ while(t.hasMoreTokens()) {
+ String s = t.nextToken();
+ if (s.indexOf('.') >= 0) {
+ // this is a delimiter
+ if (s.length() > 1) {
+ // too many dots in a row
+ throw new IllegalArgumentException();
+ }
+ balance--;
+ if (balance < 0) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ // this is an identifier segment
+ balance++;
+ SimpleName name = newSimpleName(s);
+ if (result == null) {
+ result = name;
+ } else {
+ result = newQualifiedName(result, name);
+ }
+ }
+ }
+ if (balance != 1) {
+ throw new IllegalArgumentException();
+ }
+ return result;
+ }
+
+ //=============================== TYPES ===========================
+ /**
+ * Creates and returns a new unparented simple type node with the given
+ * type name.
+ *
+ * This method can be used to convert a name (Name
) into a
+ * type (Type
) by wrapping it.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param typeName the name of the class or interface
+ * @return a new unparented simple type node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public SimpleType newSimpleType(Name typeName) {
+ SimpleType result = new SimpleType(this);
+ result.setName(typeName);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array type node with the given
+ * component type, which may be another array type.
+ *
+ * @param componentType the component type (possibly another array type)
+ * @return a new unparented array type node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public ArrayType newArrayType(Type componentType) {
+ ArrayType result = new ArrayType(this);
+ result.setComponentType(componentType);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array type node with the given
+ * element type and number of dimensions.
+ *
+ * Note that if the element type passed in is an array type, the
+ * element type of the result will not be the same as what was passed in.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param elementType the element type (never an array type)
+ * @param dimensions the number of dimensions, a positive number
+ * @return a new unparented array type node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ * - the element type is null
+ * - the element type is an array type
+ * - the number of dimensions is lower than 1
+ * - the number of dimensions is greater than 1000
+ *
+ */
+ public ArrayType newArrayType(Type elementType, int dimensions) {
+ if (elementType == null || elementType.isArrayType()) {
+ throw new IllegalArgumentException();
+ }
+ if (dimensions < 1 || dimensions > 1000) {
+ // we would blow our stacks anyway with a 1000-D array
+ throw new IllegalArgumentException();
+ }
+ ArrayType result = new ArrayType(this);
+ result.setComponentType(elementType);
+ for (int i = 2; i <= dimensions; i++) {
+ result = newArrayType(result);
+ }
+ return result;
+
+ }
+
+ /**
+ * Creates and returns a new unparented primitive type node with the given
+ * type code.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param typeCode one of the primitive type code constants declared in
+ * PrimitiveType
+ * @return a new unparented primitive type node
+ * @exception IllegalArgumentException if the primitive type code is invalid
+ */
+ public PrimitiveType newPrimitiveType(PrimitiveType.Code typeCode) {
+ PrimitiveType result = new PrimitiveType(this);
+ result.setPrimitiveTypeCode(typeCode);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new inferred type node with the given
+ * type name.
+ *
+ * @param typeName the name of the inferred type
+ * @return a new unparented inferred type node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public InferredType newInferredType(String typeName) {
+ InferredType result = new InferredType(this);
+ result.setSourceRange(-1, 0);
+ if (typeName!=null)
+ result.type=typeName;
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented qualified type node with
+ * the given qualifier type and name.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param qualifier the qualifier type node
+ * @param name the simple name being qualified
+ * @return a new unparented qualified type node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public QualifiedType newQualifiedType(Type qualifier, SimpleName name) {
+ QualifiedType result = new QualifiedType(this);
+ result.setQualifier(qualifier);
+ result.setName(name);
+ return result;
+ }
+
+ //=============================== DECLARATIONS ===========================
+ /**
+ * Creates an unparented javaScript unit node owned by this AST.
+ * The javaScript unit initially has no package declaration, no
+ * import declarations, and no type declarations.
+ *
+ * @return the new unparented javaScript unit node
+ */
+ public JavaScriptUnit newJavaScriptUnit() {
+ return new JavaScriptUnit(this);
+ }
+
+ /**
+ * Creates an unparented package declaration node owned by this AST.
+ * The package declaration initially declares a package with an
+ * unspecified name.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return the new unparented package declaration node
+ */
+ public PackageDeclaration newPackageDeclaration() {
+ PackageDeclaration result = new PackageDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented import declaration node owned by this AST.
+ * The import declaration initially contains a single-type import
+ * of a type with an unspecified name.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return the new unparented import declaration node
+ */
+ public ImportDeclaration newImportDeclaration() {
+ ImportDeclaration result = new ImportDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented class declaration node owned by this AST.
+ * The name of the class is an unspecified, but legal, name;
+ * no modifiers; no doc comment; no superclass or superinterfaces;
+ * and an empty class body.
+ *
+ * To create an interface, use this method and then call
+ * TypeDeclaration.setInterface(true)
.
+ *
+ *
+ * To create an enum declaration, use this method and then call
+ * TypeDeclaration.setEnumeration(true)
.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return a new unparented type declaration node
+ */
+ public TypeDeclaration newTypeDeclaration() {
+ TypeDeclaration result = new TypeDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented method declaration node owned by this AST.
+ * By default, the declaration is for a method of an unspecified, but
+ * legal, name; no modifiers; no doc comment; no parameters; return
+ * type void; no extra array dimensions; no thrown exceptions; and no
+ * body (as opposed to an empty body).
+ *
+ * To create a constructor, use this method and then call
+ * FunctionDeclaration.setConstructor(true)
and
+ * FunctionDeclaration.setName(className)
.
+ *
+ *
+ * @return a new unparented method declaration node
+ */
+ public FunctionDeclaration newFunctionDeclaration() {
+ FunctionDeclaration result = new FunctionDeclaration(this);
+ result.setConstructor(false);
+ return result;
+ }
+
+ /**
+ * Creates an unparented single variable declaration node owned by this AST.
+ * By default, the declaration is for a variable with an unspecified, but
+ * legal, name and type; no modifiers; no array dimensions after the
+ * variable; no initializer; not variable arity.
+ *
+ * @return a new unparented single variable declaration node
+ */
+ public SingleVariableDeclaration newSingleVariableDeclaration() {
+ SingleVariableDeclaration result = new SingleVariableDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented variable declaration fragment node owned by this
+ * AST. By default, the fragment is for a variable with an unspecified, but
+ * legal, name; no extra array dimensions; and no initializer.
+ *
+ * @return a new unparented variable declaration fragment node
+ */
+ public VariableDeclarationFragment newVariableDeclarationFragment() {
+ VariableDeclarationFragment result = new VariableDeclarationFragment(this);
+ return result;
+ }
+
+ /*
+ * Creates an unparented initializer node owned by this AST, with an
+ * empty block. By default, the initializer has no modifiers and
+ * an empty block.
+ *
+ * @return a new unparented initializer node
+ */
+ public Initializer newInitializer() {
+ Initializer result = new Initializer(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented modifier node for the given
+ * modifier.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param keyword one of the modifier keyword constants
+ * @return a new unparented modifier node
+ * @exception IllegalArgumentException if the primitive type code is invalid
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public Modifier newModifier(Modifier.ModifierKeyword keyword) {
+ Modifier result = new Modifier(this);
+ result.setKeyword(keyword);
+ return result;
+ }
+
+ /**
+ * Creates and returns a list of new unparented modifier nodes
+ * for the given modifier flags.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param flags bitwise or of modifier flags declared on {@link Modifier}
+ * @return a possibly empty list of new unparented modifier nodes
+ * (element type Modifier
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public List newModifiers(int flags) {
+ if (this.apiLevel == AST.JLS2) {
+ unsupportedIn2();
+ }
+ List result = new ArrayList(3); // 3 modifiers is more than average
+ if (Modifier.isPublic(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
+ }
+ if (Modifier.isProtected(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD));
+ }
+ if (Modifier.isPrivate(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
+ }
+ if (Modifier.isAbstract(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD));
+ }
+ if (Modifier.isStatic(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.STATIC_KEYWORD));
+ }
+ if (Modifier.isFinal(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
+ }
+ if (Modifier.isSynchronized(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD));
+ }
+ if (Modifier.isNative(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD));
+ }
+ if (Modifier.isStrictfp(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD));
+ }
+ if (Modifier.isTransient(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD));
+ }
+ if (Modifier.isVolatile(flags)) {
+ result.add(newModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD));
+ }
+ return result;
+ }
+
+ //=============================== COMMENTS ===========================
+
+ /**
+ * Creates and returns a new block comment placeholder node.
+ *
+ * Note that this node type is used to recording the source
+ * range where a comment was found in the source string.
+ * These comment nodes are normally found (only) in
+ * {@linkplain JavaScriptUnit#getCommentList()
+ * the comment table} for parsed javaScript units.
+ *
+ *
+ * @return a new unparented block comment node
+ */
+ public BlockComment newBlockComment() {
+ BlockComment result = new BlockComment(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new line comment placeholder node.
+ *
+ * Note that this node type is used to recording the source
+ * range where a comment was found in the source string.
+ * These comment nodes are normally found (only) in
+ * {@linkplain JavaScriptUnit#getCommentList()
+ * the comment table} for parsed javaScript units.
+ *
+ *
+ * @return a new unparented line comment node
+ */
+ public LineComment newLineComment() {
+ LineComment result = new LineComment(this);
+ return result;
+ }
+
+ public ListExpression newListExpression() {
+ ListExpression result = new ListExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new doc comment node.
+ * Initially the new node has an empty list of tag elements
+ * (and, for backwards compatability, an unspecified, but legal,
+ * doc comment string)
+ *
+ * @return a new unparented doc comment node
+ */
+ public JSdoc newJSdoc() {
+ JSdoc result = new JSdoc(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new tag element node.
+ * Initially the new node has no tag name and an empty list of fragments.
+ *
+ * Note that this node type is used only inside doc comments
+ * ({@link JSdoc}).
+ *
+ *
+ * @return a new unparented tag element node
+ */
+ public TagElement newTagElement() {
+ TagElement result = new TagElement(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new text element node.
+ * Initially the new node has an empty text string.
+ *
+ * Note that this node type is used only inside doc comments
+ * ({@link JSdoc Javadoc}).
+ *
+ *
+ * @return a new unparented text element node
+ */
+ public TextElement newTextElement() {
+ TextElement result = new TextElement(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new member reference node.
+ * Initially the new node has no qualifier name and
+ * an unspecified, but legal, member name.
+ *
+ * Note that this node type is used only inside doc comments
+ * ({@link JSdoc}).
+ *
+ *
+ * @return a new unparented member reference node
+ */
+ public MemberRef newMemberRef() {
+ MemberRef result = new MemberRef(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new method reference node.
+ * Initially the new node has no qualifier name,
+ * an unspecified, but legal, method name, and an
+ * empty parameter list.
+ *
+ * Note that this node type is used only inside doc comments
+ * ({@link JSdoc Javadoc}).
+ *
+ *
+ * @return a new unparented method reference node
+ */
+ public FunctionRef newFunctionRef() {
+ FunctionRef result = new FunctionRef(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new method reference node.
+ * Initially the new node has an unspecified, but legal,
+ * type, not variable arity, and no parameter name.
+ *
+ * Note that this node type is used only inside doc comments
+ * ({@link JSdoc}).
+ *
+ *
+ * @return a new unparented method reference parameter node
+ */
+ public FunctionRefParameter newFunctionRefParameter() {
+ FunctionRefParameter result = new FunctionRefParameter(this);
+ return result;
+ }
+
+ //=============================== STATEMENTS ===========================
+ /**
+ * Creates a new unparented local variable declaration statement node
+ * owned by this AST, for the given variable declaration fragment.
+ * By default, there are no modifiers and the base type is unspecified
+ * (but legal).
+ *
+ * This method can be used to convert a variable declaration fragment
+ * (VariableDeclarationFragment
) into a statement
+ * (Statement
) by wrapping it. Additional variable
+ * declaration fragments can be added afterwards.
+ *
+ *
+ * @param fragment the variable declaration fragment
+ * @return a new unparented variable declaration statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ * - the variable declaration fragment is null
+ *
+ */
+ public VariableDeclarationStatement
+ newVariableDeclarationStatement(VariableDeclarationFragment fragment) {
+ if (fragment == null) {
+ throw new IllegalArgumentException();
+ }
+ VariableDeclarationStatement result =
+ new VariableDeclarationStatement(this);
+ result.fragments().add(fragment);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented local type declaration statement node
+ * owned by this AST, for the given type declaration.
+ *
+ * This method can be used to convert a type declaration
+ * (TypeDeclaration
) into a statement
+ * (Statement
) by wrapping it.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param decl the type declaration
+ * @return a new unparented local type declaration statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public TypeDeclarationStatement
+ newTypeDeclarationStatement(TypeDeclaration decl) {
+ TypeDeclarationStatement result = new TypeDeclarationStatement(this);
+ result.setDeclaration(decl);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented local type declaration statement node
+ * owned by this AST, for the given type declaration.
+ *
+ * This method can be used to convert any kind of type declaration
+ * (AbstractTypeDeclaration
) into a statement
+ * (Statement
) by wrapping it.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param decl the type declaration
+ * @return a new unparented local type declaration statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public TypeDeclarationStatement
+ newTypeDeclarationStatement(AbstractTypeDeclaration decl) {
+ TypeDeclarationStatement result = new TypeDeclarationStatement(this);
+ if (this.apiLevel == AST.JLS2) {
+ result.internalSetTypeDeclaration((TypeDeclaration) decl);
+ }
+ if (this.apiLevel >= AST.JLS3) {
+ result.setDeclaration(decl);
+ }
+ return result;
+ }
+
+ /**
+ * Creates an unparented block node owned by this AST, for an empty list
+ * of statements.
+ *
+ * @return a new unparented, empty block node
+ */
+ public Block newBlock() {
+ return new Block(this);
+ }
+
+ /**
+ * Creates an unparented continue statement node owned by this AST.
+ * The continue statement has no label.
+ *
+ * @return a new unparented continue statement node
+ */
+ public ContinueStatement newContinueStatement() {
+ return new ContinueStatement(this);
+ }
+
+ /**
+ * Creates an unparented break statement node owned by this AST.
+ * The break statement has no label.
+ *
+ * @return a new unparented break statement node
+ */
+ public BreakStatement newBreakStatement() {
+ return new BreakStatement(this);
+ }
+
+ /**
+ * Creates a new unparented expression statement node owned by this AST,
+ * for the given expression.
+ *
+ * This method can be used to convert an expression
+ * (Expression
) into a statement (Type
)
+ * by wrapping it. Note, however, that the result is only legal for
+ * limited expression types, including method invocations, assignments,
+ * and increment/decrement operations.
+ *
+ *
+ * @param expression the expression
+ * @return a new unparented statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public ExpressionStatement newExpressionStatement(Expression expression) {
+ ExpressionStatement result = new ExpressionStatement(this);
+ result.setExpression(expression);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented if statement node owned by this AST.
+ * By default, the expression is unspecified (but legal),
+ * the then statement is an empty block, and there is no else statement.
+ *
+ * @return a new unparented if statement node
+ */
+ public IfStatement newIfStatement() {
+ return new IfStatement(this);
+ }
+
+ /**
+ * Creates a new unparented while statement node owned by this AST.
+ * By default, the expression is unspecified (but legal), and
+ * the body statement is an empty block.
+ *
+ * @return a new unparented while statement node
+ */
+ public WhileStatement newWhileStatement() {
+ return new WhileStatement(this);
+ }
+
+ /**
+ * Creates a new unparented with statement node owned by this AST.
+ * By default, the expression is unspecified (but legal), and
+ * the body statement is an empty block.
+ *
+ * @return a new unparented with statement node
+ */
+ public WithStatement newWithStatement() {
+ return new WithStatement(this);
+ }
+
+ /**
+ * Creates a new unparented do statement node owned by this AST.
+ * By default, the expression is unspecified (but legal), and
+ * the body statement is an empty block.
+ *
+ * @return a new unparented do statement node
+ */
+ public DoStatement newDoStatement() {
+ return new DoStatement(this);
+ }
+
+ /**
+ * Creates a new unparented try statement node owned by this AST.
+ * By default, the try statement has an empty block, no catch
+ * clauses, and no finally block.
+ *
+ * @return a new unparented try statement node
+ */
+ public TryStatement newTryStatement() {
+ return new TryStatement(this);
+ }
+
+ /**
+ * Creates a new unparented catch clause node owned by this AST.
+ * By default, the catch clause declares an unspecified, but legal,
+ * exception declaration and has an empty block.
+ *
+ * @return a new unparented catch clause node
+ */
+ public CatchClause newCatchClause() {
+ return new CatchClause(this);
+ }
+
+ /**
+ * Creates a new unparented return statement node owned by this AST.
+ * By default, the return statement has no expression.
+ *
+ * @return a new unparented return statement node
+ */
+ public ReturnStatement newReturnStatement() {
+ return new ReturnStatement(this);
+ }
+
+ /**
+ * Creates a new unparented throw statement node owned by this AST.
+ * By default, the expression is unspecified, but legal.
+ *
+ * @return a new unparented throw statement node
+ */
+ public ThrowStatement newThrowStatement() {
+ return new ThrowStatement(this);
+ }
+
+ /**
+ * Creates a new unparented empty statement node owned by this AST.
+ *
+ * @return a new unparented empty statement node
+ */
+ public EmptyStatement newEmptyStatement() {
+ return new EmptyStatement(this);
+ }
+
+ /**
+ * Creates a new unparented labeled statement node owned by this AST.
+ * By default, the label and statement are both unspecified, but legal.
+ *
+ * @return a new unparented labeled statement node
+ */
+ public LabeledStatement newLabeledStatement() {
+ return new LabeledStatement(this);
+ }
+
+ /**
+ * Creates a new unparented switch statement node owned by this AST.
+ * By default, the expression is unspecified, but legal, and there are
+ * no statements or switch cases.
+ *
+ * @return a new unparented labeled statement node
+ */
+ public SwitchStatement newSwitchStatement() {
+ return new SwitchStatement(this);
+ }
+
+ /**
+ * Creates a new unparented switch case statement node owned by
+ * this AST. By default, the expression is unspecified, but legal.
+ *
+ * @return a new unparented switch case node
+ */
+ public SwitchCase newSwitchCase() {
+ return new SwitchCase(this);
+ }
+
+
+ /**
+ * Creates a new unparented for statement node owned by this AST.
+ * By default, there are no initializers, no condition expression,
+ * no updaters, and the body is an empty block.
+ *
+ * @return a new unparented for statement node
+ */
+ public ForStatement newForStatement() {
+ return new ForStatement(this);
+ }
+
+ /**
+ * Creates a new unparented for..in statement node owned by this AST.
+ * By default, there are no initializers, no condition expression,
+ * no updaters, and the body is an empty block.
+ *
+ * @return a new unparented for..in statement node
+ */
+ public ForInStatement newForInStatement() {
+ return new ForInStatement(this);
+ }
+
+ /*
+ * Creates a new unparented enhanced for statement node owned by this AST.
+ * By default, the paramter and expression are unspecified
+ * but legal subtrees, and the body is an empty block.
+ *
+ * @return a new unparented throw statement node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public EnhancedForStatement newEnhancedForStatement() {
+ return new EnhancedForStatement(this);
+ }
+
+ //=============================== EXPRESSIONS ===========================
+ /**
+ * Creates and returns a new unparented string literal node for
+ * the empty string literal.
+ *
+ * @return a new unparented string literal node
+ */
+ public StringLiteral newStringLiteral() {
+ return new StringLiteral(this);
+ }
+
+
+ /**
+ * Creates and returns a new unparented character literal node.
+ * Initially the node has an unspecified character literal.
+ *
+ * @return a new unparented character literal node
+ */
+ public CharacterLiteral newCharacterLiteral() {
+ return new CharacterLiteral(this);
+ }
+
+
+
+ /**
+ * Creates and returns a new Regular Expression literal node.
+ * Initially the node has an unspecified character literal.
+ *
+ * @return a new unparented regular expression literal node
+ */ public RegularExpressionLiteral newRegularExpressionLiteral() {
+ return new RegularExpressionLiteral(this);
+ }
+/**
+ * Creates and returns a new unparented number literal node.
+ *
+ * @param literal the token for the numeric literal as it would
+ * appear in JavaScript source code
+ * @return a new unparented number literal node
+ * @exception IllegalArgumentException if the literal is null
+ */
+ public NumberLiteral newNumberLiteral(String literal) {
+ if (literal == null) {
+ throw new IllegalArgumentException();
+ }
+ NumberLiteral result = new NumberLiteral(this);
+ result.setToken(literal);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented number literal node.
+ * Initially the number literal token is "0"
.
+ *
+ * @return a new unparented number literal node
+ */
+ public NumberLiteral newNumberLiteral() {
+ NumberLiteral result = new NumberLiteral(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented null literal node.
+ *
+ * @return a new unparented null literal node
+ */
+ public NullLiteral newNullLiteral() {
+ return new NullLiteral(this);
+ }
+
+
+ /**
+ * Creates and returns a new unparented 'undefined' literal node.
+ *
+ * @return a new unparented 'undefined' literal node
+ */
+ public UndefinedLiteral newUndefinedLiteral() {
+ return new UndefinedLiteral(this);
+ }
+
+ /**
+ * Creates and returns a new unparented boolean literal node.
+ *
+ * For example, the assignment expression foo = true
+ * is generated by the following snippet:
+ *
+ *
+ * Assignment e= ast.newAssignment();
+ * e.setLeftHandSide(ast.newSimpleName("foo"));
+ * e.setRightHandSide(ast.newBooleanLiteral(true));
+ *
+ *
+ *
+ *
+ * @param value the boolean value
+ * @return a new unparented boolean literal node
+ */
+ public BooleanLiteral newBooleanLiteral(boolean value) {
+ BooleanLiteral result = new BooleanLiteral(this);
+ result.setBooleanValue(value);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented assignment expression node
+ * owned by this AST. By default, the assignment operator is "=" and
+ * the left and right hand side expressions are unspecified, but
+ * legal, names.
+ *
+ * @return a new unparented assignment expression node
+ */
+ public Assignment newAssignment() {
+ Assignment result = new Assignment(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented method invocation expression node owned by this
+ * AST. By default, the name of the method is unspecified (but legal)
+ * there is no receiver expression, no type arguments, and the list of
+ * arguments is empty.
+ *
+ * @return a new unparented method invocation expression node
+ */
+ public FunctionInvocation newFunctionInvocation() {
+ FunctionInvocation result = new FunctionInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented "super" method invocation expression node owned by
+ * this AST. By default, the name of the method is unspecified (but legal)
+ * there is no qualifier, no type arguments, and the list of arguments is empty.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return a new unparented "super" method invocation
+ * expression node
+ */
+ public SuperMethodInvocation newSuperMethodInvocation() {
+ SuperMethodInvocation result = new SuperMethodInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented alternate constructor ("this(...);") invocation
+ * statement node owned by this AST. By default, the lists of arguments
+ * and type arguments are both empty.
+ *
+ * Note that this type of node is a Statement, whereas a regular
+ * method invocation is an Expression. The only valid use of these
+ * statements are as the first statement of a constructor body.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return a new unparented alternate constructor invocation statement node
+ */
+ public ConstructorInvocation newConstructorInvocation() {
+ ConstructorInvocation result = new ConstructorInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates an unparented alternate super constructor ("super(...);")
+ * invocation statement node owned by this AST. By default, there is no
+ * qualifier, no type arguments, and the list of arguments is empty.
+ *
+ * Note that this type of node is a Statement, whereas a regular
+ * super method invocation is an Expression. The only valid use of these
+ * statements are as the first statement of a constructor body.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return a new unparented super constructor invocation statement node
+ */
+ public SuperConstructorInvocation newSuperConstructorInvocation() {
+ SuperConstructorInvocation result =
+ new SuperConstructorInvocation(this);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented local variable declaration expression node
+ * owned by this AST, for the given variable declaration fragment. By
+ * default, there are no modifiers and the base type is unspecified
+ * (but legal).
+ *
+ * This method can be used to convert a variable declaration fragment
+ * (VariableDeclarationFragment
) into an expression
+ * (Expression
) by wrapping it. Additional variable
+ * declaration fragments can be added afterwards.
+ *
+ *
+ * @param fragment the first variable declaration fragment
+ * @return a new unparented variable declaration expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ * - the given fragment is null
+ * - a cycle in would be created
+ *
+ */
+ public VariableDeclarationExpression
+ newVariableDeclarationExpression(VariableDeclarationFragment fragment) {
+ if (fragment == null) {
+ throw new IllegalArgumentException();
+ }
+ VariableDeclarationExpression result =
+ new VariableDeclarationExpression(this);
+ result.fragments().add(fragment);
+ return result;
+ }
+
+ /**
+ * Creates a new unparented field declaration node owned by this AST,
+ * for the given variable declaration fragment. By default, there are no
+ * modifiers, no doc comment, and the base type is unspecified
+ * (but legal).
+ *
+ * This method can be used to wrap a variable declaration fragment
+ * (VariableDeclarationFragment
) into a field declaration
+ * suitable for inclusion in the body of a type declaration
+ * (FieldDeclaration
implements BodyDeclaration
).
+ * Additional variable declaration fragments can be added afterwards.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param fragment the variable declaration fragment
+ * @return a new unparented field declaration node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ * - the given fragment is null
+ *
+ */
+ public FieldDeclaration newFieldDeclaration(VariableDeclarationFragment fragment) {
+ if (fragment == null) {
+ throw new IllegalArgumentException();
+ }
+ FieldDeclaration result = new FieldDeclaration(this);
+ result.fragments().add(fragment);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented "this" expression node
+ * owned by this AST. By default, there is no qualifier.
+ *
+ * @return a new unparented "this" expression node
+ */
+ public ThisExpression newThisExpression() {
+ ThisExpression result = new ThisExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented field access expression node
+ * owned by this AST. By default, the expression and field are both
+ * unspecified, but legal, names.
+ *
+ * @return a new unparented field access expression node
+ */
+ public FieldAccess newFieldAccess() {
+ FieldAccess result = new FieldAccess(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented super field access expression node
+ * owned by this AST. By default, the expression and field are both
+ * unspecified, but legal, names.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return a new unparented super field access expression node
+ */
+ public SuperFieldAccess newSuperFieldAccess() {
+ SuperFieldAccess result = new SuperFieldAccess(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented type literal expression node
+ * owned by this AST. By default, the type is unspecified (but legal).
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return a new unparented type literal node
+ */
+ public TypeLiteral newTypeLiteral() {
+ TypeLiteral result = new TypeLiteral(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented function expression node
+ * owned by this AST.
+ *
+ * @return a new unparented function expression node
+ */
+ public FunctionExpression newFunctionExpression() {
+ FunctionExpression result = new FunctionExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented object literal expression node
+ * owned by this AST.
+ *
+ * @return a new unparented object literal expression node
+ */
+ public ObjectLiteral newObjectLiteral() {
+ ObjectLiteral result = new ObjectLiteral(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented object literal field expression node
+ * owned by this AST.
+ *
+ * @return a new unparented object literal field expression node
+ */
+ public ObjectLiteralField newObjectLiteralField() {
+ ObjectLiteralField result = new ObjectLiteralField(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented parenthesized expression node
+ * owned by this AST. By default, the expression is unspecified (but legal).
+ *
+ * @return a new unparented parenthesized expression node
+ */
+ public ParenthesizedExpression newParenthesizedExpression() {
+ ParenthesizedExpression result = new ParenthesizedExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented infix expression node
+ * owned by this AST. By default, the operator and left and right
+ * operand are unspecified (but legal), and there are no extended
+ * operands.
+ *
+ * @return a new unparented infix expression node
+ */
+ public InfixExpression newInfixExpression() {
+ InfixExpression result = new InfixExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented instanceof expression node
+ * owned by this AST. By default, the operator and left and right
+ * operand are unspecified (but legal).
+ *
+ * @return a new unparented instanceof expression node
+ */
+ public InstanceofExpression newInstanceofExpression() {
+ InstanceofExpression result = new InstanceofExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented postfix expression node
+ * owned by this AST. By default, the operator and operand are
+ * unspecified (but legal).
+ *
+ * @return a new unparented postfix expression node
+ */
+ public PostfixExpression newPostfixExpression() {
+ PostfixExpression result = new PostfixExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented prefix expression node
+ * owned by this AST. By default, the operator and operand are
+ * unspecified (but legal).
+ *
+ * @return a new unparented prefix expression node
+ */
+ public PrefixExpression newPrefixExpression() {
+ PrefixExpression result = new PrefixExpression(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array access expression node
+ * owned by this AST. By default, the array and index expression are
+ * both unspecified (but legal).
+ *
+ * @return a new unparented array access expression node
+ */
+ public ArrayAccess newArrayAccess() {
+ ArrayAccess result = new ArrayAccess(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array creation expression node
+ * owned by this AST. By default, the array type is an unspecified
+ * 1-dimensional array, the list of dimensions is empty, and there is no
+ * array initializer.
+ *
+ * @return a new unparented array creation expression node
+ */
+ public ArrayCreation newArrayCreation() {
+ ArrayCreation result = new ArrayCreation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented class instance creation
+ * ("new") expression node owned by this AST. By default,
+ * there is no qualifying expression, no type parameters,
+ * an unspecified (but legal) type name, an empty list of
+ * arguments, and does not declare an anonymous class declaration.
+ *
+ * @return a new unparented class instance creation expression node
+ */
+ public ClassInstanceCreation newClassInstanceCreation() {
+ ClassInstanceCreation result = new ClassInstanceCreation(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented anonymous class declaration
+ * node owned by this AST. By default, the body declaration list is empty.
+ *
+ * @return a new unparented anonymous class declaration node
+ */
+ public AnonymousClassDeclaration newAnonymousClassDeclaration() {
+ AnonymousClassDeclaration result = new AnonymousClassDeclaration(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented array initializer node
+ * owned by this AST. By default, the initializer has no expressions.
+ *
+ * @return a new unparented array initializer node
+ */
+ public ArrayInitializer newArrayInitializer() {
+ ArrayInitializer result = new ArrayInitializer(this);
+ return result;
+ }
+
+ /**
+ * Creates and returns a new unparented conditional expression node
+ * owned by this AST. By default, the condition and both expressions
+ * are unspecified (but legal).
+ *
+ * @return a new unparented array conditional expression node
+ */
+ public ConditionalExpression newConditionalExpression() {
+ ConditionalExpression result = new ConditionalExpression(this);
+ return result;
+ }
+
+ /**
+ * Enables the recording of changes to the given compilation
+ * unit and its descendents. The javaScript unit must have
+ * been created by ASTParser
and still be in
+ * its original state. Once recording is on,
+ * arbitrary changes to the subtree rooted at the compilation
+ * unit are recorded internally. Once the modification has
+ * been completed, call rewrite
to get an object
+ * representing the corresponding edits to the original
+ * source code string.
+ *
+ * @exception IllegalArgumentException if this javaScript unit is
+ * marked as unmodifiable, or if this javaScript unit has already
+ * been tampered with, or if recording has already been enabled,
+ * or if root
is not owned by this AST
+ * @see JavaScriptUnit#recordModifications()
+ */
+ void recordModifications(JavaScriptUnit root) {
+ if(this.modificationCount != this.originalModificationCount) {
+ throw new IllegalArgumentException("AST is already modified"); //$NON-NLS-1$
+ } else if(this.rewriter != null) {
+ throw new IllegalArgumentException("AST modifications are already recorded"); //$NON-NLS-1$
+ } else if((root.getFlags() & ASTNode.PROTECT) != 0) {
+ throw new IllegalArgumentException("Root node is unmodifiable"); //$NON-NLS-1$
+ } else if(root.getAST() != this) {
+ throw new IllegalArgumentException("Root node is not owned by this ast"); //$NON-NLS-1$
+ }
+
+ this.rewriter = new InternalASTRewrite(root);
+ this.setEventHandler(this.rewriter);
+ }
+
+ /**
+ * Converts all modifications recorded into an object
+ * representing the corresponding text edits to the
+ * given document containing the original source
+ * code for the javaScript unit that gave rise to
+ * this AST.
+ *
+ * @param document original document containing source code
+ * for the javaScript unit
+ * @param options the table of formatter options
+ * (key type: String
; value type: String
);
+ * or null
to use the standard global options
+ * {@link JavaScriptCore#getOptions() JavaScriptCore.getOptions()}.
+ * @return text edit object describing the changes to the
+ * document corresponding to the recorded AST modifications
+ * @exception IllegalArgumentException if the document passed is
+ * null
or does not correspond to this AST
+ * @exception IllegalStateException if recordModifications
+ * was not called to enable recording
+ * @see JavaScriptUnit#rewrite(IDocument, Map)
+ */
+ TextEdit rewrite(IDocument document, Map options) {
+ if (document == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.rewriter == null) {
+ throw new IllegalStateException("Modifications record is not enabled"); //$NON-NLS-1$
+ }
+ return this.rewriter.rewriteAST(document, options);
+ }
+ /**
+ * Returns true if the ast tree was created with bindings, false otherwise
+ *
+ * @return true if the ast tree was created with bindings, false otherwise
+ */
+ public boolean hasResolvedBindings() {
+ return (this.bits & RESOLVED_BINDINGS) != 0;
+ }
+
+ /**
+ * Returns true if the ast tree was created with statements recovery, false otherwise
+ *
+ * @return true if the ast tree was created with statements recovery, false otherwise
+ */
+ public boolean hasStatementsRecovery() {
+ return (this.bits & IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
+ }
+
+ /**
+ * Returns true if the ast tree was created with bindings recovery, false otherwise
+ *
+ * @return true if the ast tree was created with bindings recovery, false otherwise
+ */
+ public boolean hasBindingsRecovery() {
+ return (this.bits & IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY) != 0;
+ }
+
+ void setFlag(int newValue) {
+ this.bits |= newValue;
+ }
+
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java
new file mode 100644
index 0000000..17ead42
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTConverter.java
@@ -0,0 +1,4501 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * bug 227489 - Etienne Pfister
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.core.dom.Modifier.ModifierKeyword;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArgumentExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteralConcatenation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Internal class for converting internal compiler ASTs into public ASTs.
+ */
+class ASTConverter {
+
+ protected AST ast;
+ protected Comment[] commentsTable;
+ char[] compilationUnitSource;
+ int compilationUnitSourceLength;
+ protected DocCommentParser docParser;
+ // comments
+ protected boolean insideComments;
+ protected IProgressMonitor monitor;
+ protected Set pendingNameScopeResolution;
+ protected Set pendingThisExpressionScopeResolution;
+ protected boolean resolveBindings;
+ Scanner scanner;
+ private DefaultCommentMapper commentMapper;
+
+ public ASTConverter(Map options, boolean resolveBindings, IProgressMonitor monitor) {
+ this.resolveBindings = resolveBindings;
+ Object sourceModeSetting = options.get(JavaScriptCore.COMPILER_SOURCE);
+ long sourceLevel = ClassFileConstants.JDK1_3;
+ if (JavaScriptCore.VERSION_1_4.equals(sourceModeSetting)) {
+ sourceLevel = ClassFileConstants.JDK1_4;
+ } else if (JavaScriptCore.VERSION_1_5.equals(sourceModeSetting)) {
+ sourceLevel = ClassFileConstants.JDK1_5;
+ }
+
+ this.scanner = new Scanner(
+ true /*comment*/,
+ false /*whitespace*/,
+ false /*nls*/,
+ sourceLevel /*sourceLevel*/,
+ null /*taskTags*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ this.monitor = monitor;
+ this.insideComments = JavaScriptCore.ENABLED.equals(options.get(JavaScriptCore.COMPILER_DOC_COMMENT_SUPPORT));
+ }
+
+ protected void adjustSourcePositionsForParent(org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression) {
+ int start = expression.sourceStart;
+ int end = expression.sourceEnd;
+ int leftParentCount = 1;
+ int rightParentCount = 0;
+ this.scanner.resetTo(start, end);
+ try {
+ int token = this.scanner.getNextToken();
+ expression.sourceStart = this.scanner.currentPosition;
+ boolean stop = false;
+ while (!stop && ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)) {
+ switch(token) {
+ case TerminalTokens.TokenNameLPAREN:
+ leftParentCount++;
+ break;
+ case TerminalTokens.TokenNameRPAREN:
+ rightParentCount++;
+ if (rightParentCount == leftParentCount) {
+ // we found the matching parenthesis
+ stop = true;
+ }
+ }
+ }
+ expression.sourceEnd = this.scanner.startPosition - 1;
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ protected void addStatementsToBlock(org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] statements, Block block) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ if (statements[i] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+ checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+ }
+ else if (statements[i] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration) { // fix for inner function handling, Etienne Pfister
+ org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration method = (org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration) statements[i];
+ block.statements().add(convert(method));
+ }
+ else {
+ Statement statement = convert(statements[i]);
+ if (statement != null) {
+ block.statements().add(statement);
+ }
+ }
+ }
+ }
+
+ protected void buildBodyDeclarations(org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration, AbstractTypeDeclaration typeDecl) {
+ // add body declaration in the lexical order
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] members = typeDeclaration.memberTypes;
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration[] fields = typeDeclaration.fields;
+ org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+
+ int fieldsLength = fields == null? 0 : fields.length;
+ int methodsLength = methods == null? 0 : methods.length;
+ int membersLength = members == null ? 0 : members.length;
+ int fieldsIndex = 0;
+ int methodsIndex = 0;
+ int membersIndex = 0;
+
+ while ((fieldsIndex < fieldsLength)
+ || (membersIndex < membersLength)
+ || (methodsIndex < methodsLength)) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+ org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldsIndex < fieldsLength) {
+ nextFieldDeclaration = fields[fieldsIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodsIndex < methodsLength) {
+ nextMethodDeclaration = methods[methodsIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (membersIndex < membersLength) {
+ nextMemberDeclaration = members[membersIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, typeDecl.bodyDeclarations());
+ fieldsIndex++;
+ break;
+ case 1 :
+ methodsIndex++;
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+ typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
+ }
+ break;
+ case 2 :
+ membersIndex++;
+ ASTNode node = convert(nextMemberDeclaration);
+ if (node == null) {
+ typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+ } else {
+ typeDecl.bodyDeclarations().add(node);
+ }
+ }
+ }
+ // Convert javadoc
+ convert(typeDeclaration.javadoc, typeDecl);
+ }
+
+
+ protected void buildBodyDeclarations(org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
+ // add body declaration in the lexical order
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] members = expression.memberTypes;
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration[] fields = expression.fields;
+ org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = expression.methods;
+
+ int fieldsLength = fields == null? 0 : fields.length;
+ int methodsLength = methods == null? 0 : methods.length;
+ int membersLength = members == null ? 0 : members.length;
+ int fieldsIndex = 0;
+ int methodsIndex = 0;
+ int membersIndex = 0;
+
+ while ((fieldsIndex < fieldsLength)
+ || (membersIndex < membersLength)
+ || (methodsIndex < methodsLength)) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+ org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldsIndex < fieldsLength) {
+ nextFieldDeclaration = fields[fieldsIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodsIndex < methodsLength) {
+ nextMethodDeclaration = methods[methodsIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (membersIndex < membersLength) {
+ nextMemberDeclaration = members[membersIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, anonymousClassDeclaration.bodyDeclarations());
+ fieldsIndex++;
+ break;
+ case 1 :
+ methodsIndex++;
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+ anonymousClassDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+ }
+ break;
+ case 2 :
+ membersIndex++;
+ ASTNode node = convert(nextMemberDeclaration);
+ if (node == null) {
+ anonymousClassDeclaration.setFlags(anonymousClassDeclaration.getFlags() | ASTNode.MALFORMED);
+ } else {
+ anonymousClassDeclaration.bodyDeclarations().add(node);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param compilationUnit
+ * @param comments
+ */
+ void buildCommentsTable(JavaScriptUnit compilationUnit, int[][] comments) {
+ // Build comment table
+ this.commentsTable = new Comment[comments.length];
+ int nbr = 0;
+ for (int i = 0; i < comments.length; i++) {
+ Comment comment = createComment(comments[i]);
+ if (comment != null) {
+ comment.setAlternateRoot(compilationUnit);
+ this.commentsTable[nbr++] = comment;
+ }
+ }
+ // Resize table if necessary
+ if (nbr 0 && fields[index - 1].declarationSourceStart == fields[index].declarationSourceStart) {
+ // we have a multiple field declaration
+ // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclarations.get(bodyDeclarations.size() - 1);
+ fieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fields[index]));
+ } else {
+ // we can create a new FieldDeclaration
+ bodyDeclarations.add(convertToFieldDeclaration(fields[index]));
+ }
+ }
+
+ protected void checkAndAddMultipleLocalDeclaration(org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement[] stmts, int index, List blockStatements) {
+// if (index > 0
+// && stmts[index - 1] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+// org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration local1 = (org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) stmts[index - 1];
+// org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration local2 = (org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) stmts[index];
+// if (local1.declarationSourceStart == local2.declarationSourceStart) {
+// // we have a multiple local declarations
+// // We retrieve the existing VariableDeclarationStatement to add the new VariableDeclarationFragment
+// VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) blockStatements.get(blockStatements.size() - 1);
+// variableDeclarationStatement.fragments().add(convertToVariableDeclarationFragment((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+// } else {
+// // we can create a new FieldDeclaration
+// blockStatements.add(convertToVariableDeclarationStatement((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+// }
+// } else {
+// // we can create a new FieldDeclaration
+// blockStatements.add(convertToVariableDeclarationStatement((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+// }
+ VariableDeclarationStatement variableDeclarationStatement = convertToVariableDeclarationStatement((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)stmts[index]);
+ blockStatements.add(variableDeclarationStatement);
+ }
+
+ protected void checkCanceled() {
+ if (this.monitor != null && this.monitor.isCanceled())
+ throw new OperationCanceledException();
+ }
+
+ protected void completeRecord(ArrayType arrayType, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode astNode) {
+ ArrayType array = arrayType;
+ int dimensions = array.getDimensions();
+ for (int i = 0; i < dimensions; i++) {
+ Type componentType = array.getComponentType();
+ this.recordNodes(componentType, astNode);
+ if (componentType.isArrayType()) {
+ array = (ArrayType) componentType;
+ }
+ }
+ }
+
+
+ public ASTNode convert(org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
+ checkCanceled();
+ FunctionDeclaration methodDecl = new FunctionDeclaration(this.ast);
+ setModifiers(methodDecl, methodDeclaration);
+ boolean isConstructor = methodDeclaration.isConstructor();
+ methodDecl.setConstructor(isConstructor);
+ int start = methodDeclaration.sourceStart;
+ int end;
+ SimpleName methodName =null;
+ if (methodDeclaration.selector!=null)
+ {
+ methodName = new SimpleName(this.ast);
+ methodName.internalSetIdentifier(new String(methodDeclaration.selector));
+ end = retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd);
+
+ methodName.setSourceRange(start, end - start + 1);
+ methodDecl.setName(methodName);
+ }
+ else
+ end= methodDeclaration.sourceStart;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Argument[] parameters = methodDeclaration.arguments;
+ if (parameters != null) {
+ int parametersLength = parameters.length;
+ for (int i = 0; i < parametersLength; i++) {
+ methodDecl.parameters().add(convert(parameters[i]));
+ }
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null;
+ /* need this check because a constructor could have been made a constructor after the
+ * method declaration was created, and thus it is not a ConstructorDeclaration
+ */
+ if (isConstructor && methodDeclaration instanceof ConstructorDeclaration) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ explicitConstructorCall = constructorDeclaration.constructorCall;
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ // set the return type to VOID
+ PrimitiveType returnType = new PrimitiveType(this.ast);
+ returnType.setPrimitiveTypeCode(PrimitiveType.VOID);
+ returnType.setSourceRange(methodDeclaration.sourceStart, 0);
+ methodDecl.internalSetReturnType(returnType);
+ break;
+ case AST.JLS3 :
+ methodDecl.setReturnType2(null);
+ }
+ } else if (methodDeclaration instanceof org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration method = (org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration) methodDeclaration;
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference typeReference = method.returnType;
+ if (typeReference != null) {
+ Type returnType = convertType(typeReference,method.inferredType);
+ // get the positions of the right parenthesis
+ int rightParenthesisPosition = retrieveEndOfRightParenthesisPosition(end, method.bodyEnd);
+ int extraDimensions = retrieveExtraDimension(rightParenthesisPosition, method.bodyEnd);
+ methodDecl.setExtraDimensions(extraDimensions);
+ setTypeForMethodDeclaration(methodDecl, returnType, extraDimensions);
+ } else {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ methodDecl.setReturnType2(null);
+ }
+ }
+ }
+ int declarationSourceStart = methodDeclaration.declarationSourceStart;
+ int declarationSourceEnd = methodDeclaration.bodyEnd;
+ methodDecl.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+ int closingPosition = retrieveRightBraceOrSemiColonPosition(methodDeclaration.bodyEnd + 1, methodDeclaration.declarationSourceEnd);
+ if (closingPosition != -1) {
+ int startPosition = methodDecl.getStartPosition();
+ methodDecl.setSourceRange(startPosition, closingPosition - startPosition + 1);
+
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements;
+
+ start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
+ end = retrieveEndBlockPosition(methodDeclaration.sourceStart, methodDeclaration.declarationSourceEnd);
+ Block block = null;
+ if (start != -1 && end != -1) {
+ /*
+ * start or end can be equal to -1 if we have an interface's method.
+ */
+ block = new Block(this.ast);
+ block.setSourceRange(start, end - start + 1);
+ methodDecl.setBody(block);
+ }
+ if (block != null && (statements != null || explicitConstructorCall != null)) {
+ if (explicitConstructorCall != null && explicitConstructorCall.accessMode != org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall.ImplicitSuper) {
+ block.statements().add(convert(explicitConstructorCall));
+ }
+ if (statements != null) {
+ addStatementsToBlock(statements, block);
+ }
+ }
+ if (block != null && (Modifier.isAbstract(methodDecl.getModifiers()) || Modifier.isNative(methodDecl.getModifiers()))) {
+ methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+ }
+ } else {
+ // syntax error in this method declaration
+ if (!methodDeclaration.isAbstract()) {
+ start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
+ end = methodDeclaration.bodyEnd;
+ // try to get the best end position
+ CategorizedProblem[] problems = methodDeclaration.compilationResult().problems;
+ if (problems != null) {
+ for (int i = 0, max = methodDeclaration.compilationResult().problemCount; i < max; i++) {
+ CategorizedProblem currentProblem = problems[i];
+ if (currentProblem.getSourceStart() == start && currentProblem.getID() == IProblem.ParsingErrorInsertToComplete) {
+ end = currentProblem.getSourceEnd();
+ break;
+ }
+ }
+ }
+ int startPosition = methodDecl.getStartPosition();
+ methodDecl.setSourceRange(startPosition, end - startPosition + 1);
+ if (start != -1 && end != -1) {
+ /*
+ * start or end can be equal to -1 if we have an interface's method.
+ */
+ Block block = new Block(this.ast);
+ block.setSourceRange(start, end - start + 1);
+ methodDecl.setBody(block);
+ }
+ }
+ }
+
+ // The jsdoc comment is now got from list store in javaScript unit declaration
+ convert(methodDeclaration.javadoc, methodDecl);
+ if (this.resolveBindings) {
+ recordNodes(methodDecl, methodDeclaration);
+ if (methodName!=null)
+ recordNodes(methodName, methodDeclaration);
+ methodDecl.resolveBinding();
+ }
+ return methodDecl;
+ }
+
+ public ClassInstanceCreation convert(org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression expression) {
+ ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(classInstanceCreation, expression);
+ }
+ if (expression.type!=null) {
+ switch (this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL:
+ classInstanceCreation.internalSetName(convert(expression.type));
+ break;
+ case AST.JLS3:
+ classInstanceCreation.setType(convertType(expression.type));
+ }
+ }
+ classInstanceCreation.setMember(convert(expression.member));
+ classInstanceCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ classInstanceCreation.arguments().add(convert(arguments[i]));
+ }
+ }
+ removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+ return classInstanceCreation;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ final int expressionOperatorID = (expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+ if (expression.left instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression
+ && ((expression.left.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+ // create an extended string literal equivalent => use the extended operands list
+ infixExpression.extendedOperands().add(convert(expression.right));
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression leftOperand = expression.left;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression rightOperand = null;
+ do {
+ rightOperand = ((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+ if ((((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+ && ((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+ || ((rightOperand instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression
+ && ((rightOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+ && ((rightOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+ List extendedOperands = infixExpression.extendedOperands();
+ InfixExpression temp = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ Expression leftSide = convert(leftOperand);
+ temp.setLeftOperand(leftSide);
+ temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+ int size = extendedOperands.size();
+ for (int i = 0; i < size - 1; i++) {
+ Expression expr = temp;
+ temp = new InfixExpression(this.ast);
+
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setLeftOperand(expr);
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+ }
+ infixExpression = temp;
+ for (int i = 0; i < size; i++) {
+ Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+ temp.setRightOperand(extendedOperand);
+ int startPosition = temp.getLeftOperand().getStartPosition();
+ temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+ if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+ temp = (InfixExpression) temp.getLeftOperand();
+ }
+ }
+ int startPosition = infixExpression.getLeftOperand().getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ return infixExpression;
+ }
+ infixExpression.extendedOperands().add(0, convert(rightOperand));
+ leftOperand = ((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+ } while (leftOperand instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+ Expression leftExpression = convert(leftOperand);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+
+
+
+ public SingleVariableDeclaration convert(org.eclipse.wst.jsdt.internal.compiler.ast.Argument argument) {
+ SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+ setModifiers(variableDecl, argument);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(argument.name));
+ int start = argument.sourceStart;
+ int nameEnd = argument.sourceEnd;
+ name.setSourceRange(start, nameEnd - start + 1);
+ variableDecl.setName(name);
+// final int typeSourceEnd = argument.type.sourceEnd;
+ final int extraDimensions = 0;
+// final int extraDimensions = retrieveExtraDimension(nameEnd + 1, typeSourceEnd);
+// variableDecl.setExtraDimensions(extraDimensions);
+// final boolean isVarArgs = argument.isVarArgs();
+// if (isVarArgs && extraDimensions == 0) {
+// // remove the ellipsis from the type source end
+// argument.type.sourceEnd = retrieveEllipsisStartPosition(argument.type.sourceStart, typeSourceEnd);
+// }
+ Type type = convertType(argument.type,argument.inferredType);
+// int typeEnd = type.getStartPosition() + type.getLength() - 1;
+// int rightEnd = Math.max(typeEnd, argument.declarationSourceEnd);
+ int rightEnd = argument.declarationSourceEnd;
+ /*
+ * There is extra work to do to set the proper type positions
+ * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+ */
+// if (isVarArgs) {
+// setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
+// if (extraDimensions != 0) {
+// variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+// }
+// } else {
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+// }
+ variableDecl.setSourceRange(argument.declarationSourceStart, rightEnd - argument.declarationSourceStart + 1);
+
+// if (isVarArgs) {
+// switch(this.ast.apiLevel) {
+// case AST.JLS2_INTERNAL :
+// variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+// break;
+// case AST.JLS3 :
+// variableDecl.setVarargs(true);
+// }
+// }
+ if (this.resolveBindings) {
+ recordNodes(name, argument);
+ recordNodes(variableDecl, argument);
+ variableDecl.resolveBinding();
+ }
+ return variableDecl;
+ }
+
+
+ public ArrayCreation convert(org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression expression) {
+ ArrayCreation arrayCreation = new ArrayCreation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(arrayCreation, expression);
+ }
+ arrayCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] dimensions = expression.dimensions;
+
+ int dimensionsLength = dimensions.length;
+ for (int i = 0; i < dimensionsLength; i++) {
+ if (dimensions[i] != null) {
+ Expression dimension = convert(dimensions[i]);
+ if (this.resolveBindings) {
+ recordNodes(dimension, dimensions[i]);
+ }
+ arrayCreation.dimensions().add(dimension);
+ }
+ }
+ Type type = convertType(expression.type);
+ if (this.resolveBindings) {
+ recordNodes(type, expression.type);
+ }
+ ArrayType arrayType = null;
+ if (type.isArrayType()) {
+ arrayType = (ArrayType) type;
+ } else {
+ arrayType = this.ast.newArrayType(type, dimensionsLength);
+ if (this.resolveBindings) {
+ completeRecord(arrayType, expression);
+ }
+ int start = type.getStartPosition();
+ int end = type.getStartPosition() + type.getLength();
+ int previousSearchStart = end;
+ ArrayType componentType = (ArrayType) type.getParent();
+ for (int i = 0; i < dimensionsLength; i++) {
+ previousSearchStart = retrieveRightBracketPosition(previousSearchStart + 1, this.compilationUnitSourceLength);
+ componentType.setSourceRange(start, previousSearchStart - start + 1);
+ componentType = (ArrayType) componentType.getParent();
+ }
+ }
+ arrayCreation.setType(arrayType);
+ if (this.resolveBindings) {
+ recordNodes(arrayType, expression);
+ }
+ if (expression.initializer != null) {
+ arrayCreation.setInitializer(convert(expression.initializer));
+ }
+ return arrayCreation;
+ }
+
+ public ArrayInitializer convert(org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer expression) {
+ ArrayInitializer arrayInitializer = new ArrayInitializer(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(arrayInitializer, expression);
+ }
+ arrayInitializer.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] expressions = expression.expressions;
+ if (expressions != null) {
+ int length = expressions.length;
+ for (int i = 0; i < length; i++) {
+ Expression expr = convert(expressions[i]);
+ if (this.resolveBindings) {
+ recordNodes(expr, expressions[i]);
+ }
+ arrayInitializer.expressions().add(expr);
+ }
+ }
+ return arrayInitializer;
+ }
+
+ public ArrayAccess convert(org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference reference) {
+ ArrayAccess arrayAccess = new ArrayAccess(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(arrayAccess, reference);
+ }
+ arrayAccess.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+ arrayAccess.setArray(convert(reference.receiver));
+ arrayAccess.setIndex(convert(reference.position));
+ return arrayAccess;
+ }
+
+ public Assignment convert(org.eclipse.wst.jsdt.internal.compiler.ast.Assignment expression) {
+ Assignment assignment = new Assignment(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(assignment, expression);
+ }
+ Expression lhs = convert(expression.lhs);
+ assignment.setLeftHandSide(lhs);
+ assignment.setOperator(Assignment.Operator.ASSIGN);
+ assignment.setRightHandSide(convert(expression.expression));
+ int start = lhs.getStartPosition();
+ assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+ return assignment;
+ }
+
+ /*
+ * Internal use only
+ * Used to convert class body declarations
+ */
+ public JavaScriptUnit convert(org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode[] nodes, JavaScriptUnit compilationUnit) {
+// typeDecl.setInterface(false);
+ int nodesLength = nodes.length;
+ for (int i = 0; i < nodesLength; i++) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = nodes[i];
+ if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Initializer) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Initializer oldInitializer = (org.eclipse.wst.jsdt.internal.compiler.ast.Initializer) node;
+ Initializer initializer = new Initializer(this.ast);
+ initializer.setBody(convert(oldInitializer.block));
+ setModifiers(initializer, oldInitializer);
+ initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
+// setJavaDocComment(initializer);
+// initializer.setJavadoc(convert(oldInitializer.javadoc));
+ convert(oldInitializer.javadoc, initializer);
+ compilationUnit.statements().add(initializer);
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) node;
+ if (i > 0
+ && (nodes[i - 1] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration)
+ && ((org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration)nodes[i - 1]).declarationSourceStart == fieldDeclaration.declarationSourceStart) {
+ // we have a multiple field declaration
+ // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+ FieldDeclaration currentFieldDeclaration = (FieldDeclaration) compilationUnit.statements().get(compilationUnit.statements().size() - 1);
+ currentFieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fieldDeclaration));
+ } else {
+ // we can create a new FieldDeclaration
+ compilationUnit.statements().add(convertToFieldDeclaration(fieldDeclaration));
+ }
+ } else if(node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration) {
+ AbstractMethodDeclaration nextMethodDeclaration = (AbstractMethodDeclaration) node;
+ if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+ compilationUnit.statements().add(convert(nextMethodDeclaration));
+ }
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration localDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) node;
+ if (i > 0
+ && (nodes[i - 1] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration)
+ && ((org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration)nodes[i - 1]).declarationSourceStart == localDeclaration.declarationSourceStart) {
+ // we have a multiple field declaration
+ // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+ FieldDeclaration currentFieldDeclaration = (FieldDeclaration) compilationUnit.statements().get(compilationUnit.statements().size() - 1);
+ currentFieldDeclaration.fragments().add(convertToVariableDeclarationFragment(localDeclaration));
+ } else {
+ // we can create a new FieldDeclaration
+ compilationUnit.statements().add(convertToFieldDeclaration(localDeclaration));
+ }
+ }
+// else if(node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+// org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) node;
+// ASTNode nextMemberDeclarationNode = convert(nextMemberDeclaration);
+// if (nextMemberDeclarationNode == null) {
+// typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+// } else {
+// typeDecl.bodyDeclarations().add(nextMemberDeclarationNode);
+// }
+// }
+ }
+ return compilationUnit;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+
+ int expressionOperatorID = (expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+ switch (expressionOperatorID) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.LESS_EQUALS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.GREATER_EQUALS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+ infixExpression.setOperator(InfixExpression.Operator.LEFT_SHIFT);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+ infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_SIGNED);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+ infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.OR_OR :
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.AND_AND :
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.PLUS :
+ infixExpression.setOperator(InfixExpression.Operator.PLUS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MINUS :
+ infixExpression.setOperator(InfixExpression.Operator.MINUS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.REMAINDER :
+ infixExpression.setOperator(InfixExpression.Operator.REMAINDER);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.XOR :
+ infixExpression.setOperator(InfixExpression.Operator.XOR);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.AND :
+ infixExpression.setOperator(InfixExpression.Operator.AND);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+ infixExpression.setOperator(InfixExpression.Operator.TIMES);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.OR :
+ infixExpression.setOperator(InfixExpression.Operator.OR);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.DIVIDE :
+ infixExpression.setOperator(InfixExpression.Operator.DIVIDE);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.GREATER :
+ infixExpression.setOperator(InfixExpression.Operator.GREATER);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LESS :
+ infixExpression.setOperator(InfixExpression.Operator.LESS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.INSTANCEOF :
+ infixExpression.setOperator(InfixExpression.Operator.INSTANCEOF);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.IN:
+ infixExpression.setOperator(InfixExpression.Operator.IN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.EQUAL_EQUAL_EQUAL);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.NOT_EQUAL_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.NOT_EQUAL_EQUAL);
+ break;
+ }
+
+ if (expression.left instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression
+ && ((expression.left.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+ // create an extended string literal equivalent => use the extended operands list
+ infixExpression.extendedOperands().add(convert(expression.right));
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression leftOperand = expression.left;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression rightOperand = null;
+ do {
+ rightOperand = ((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+ if ((((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+ && ((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+ || ((rightOperand instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression
+ && ((rightOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+ && ((rightOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+ List extendedOperands = infixExpression.extendedOperands();
+ InfixExpression temp = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ Expression leftSide = convert(leftOperand);
+ temp.setLeftOperand(leftSide);
+ temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+ int size = extendedOperands.size();
+ for (int i = 0; i < size - 1; i++) {
+ Expression expr = temp;
+ temp = new InfixExpression(this.ast);
+
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setLeftOperand(expr);
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+ }
+ infixExpression = temp;
+ for (int i = 0; i < size; i++) {
+ Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+ temp.setRightOperand(extendedOperand);
+ int startPosition = temp.getLeftOperand().getStartPosition();
+ temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+ if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+ temp = (InfixExpression) temp.getLeftOperand();
+ }
+ }
+ int startPosition = infixExpression.getLeftOperand().getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ return infixExpression;
+ }
+ infixExpression.extendedOperands().add(0, convert(rightOperand));
+ leftOperand = ((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+ } while (leftOperand instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+ Expression leftExpression = convert(leftOperand);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ } else if (expression.left instanceof StringLiteralConcatenation
+ && ((expression.left.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)
+ && (OperatorIds.PLUS == expressionOperatorID)) {
+ StringLiteralConcatenation literal = (StringLiteralConcatenation) expression.left;
+ final org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] stringLiterals = literal.literals;
+ infixExpression.setLeftOperand(convert(stringLiterals[0]));
+ infixExpression.setRightOperand(convert(stringLiterals[1]));
+ for (int i = 2; i < literal.counter; i++) {
+ infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+ }
+ infixExpression.extendedOperands().add(convert(expression.right));
+ int startPosition = literal.sourceStart;
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+
+ public Block convert(org.eclipse.wst.jsdt.internal.compiler.ast.Block statement) {
+ Block block = new Block(this.ast);
+ if (statement.sourceEnd > 0) {
+ block.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] statements = statement.statements;
+ if (statements != null) {
+ addStatementsToBlock(statements, block);
+ }
+ return block;
+ }
+
+ public BreakStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.BreakStatement statement) {
+ BreakStatement breakStatement = new BreakStatement(this.ast);
+ breakStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ if (statement.label != null) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(statement.label));
+ retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+ breakStatement.setLabel(name);
+ }
+ return breakStatement;
+ }
+
+
+ public SwitchCase convert(org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement statement) {
+ SwitchCase switchCase = new SwitchCase(this.ast);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression constantExpression = statement.constantExpression;
+ if (constantExpression == null) {
+ switchCase.setExpression(null);
+ } else {
+ switchCase.setExpression(convert(constantExpression));
+ }
+ switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ retrieveColonPosition(switchCase);
+ return switchCase;
+ }
+
+ public FunctionExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression expression) {
+ FunctionExpression functionExpression = new FunctionExpression(this.ast);
+ int sourceEnd = expression.sourceEnd;
+ if (sourceEnd==0)
+ sourceEnd=expression.methodDeclaration.bodyEnd;
+ functionExpression.setSourceRange(expression.sourceStart, sourceEnd - expression.sourceStart + 1);
+
+ functionExpression.setMethod((FunctionDeclaration)convert(expression.methodDeclaration));
+ if (this.resolveBindings) {
+ recordNodes(functionExpression, expression);
+ }
+ return functionExpression;
+ }
+
+ public ObjectLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral objLiteral) {
+ ObjectLiteral objectLiteral = new ObjectLiteral(this.ast);
+ objectLiteral.setSourceRange(objLiteral.sourceStart, objLiteral.sourceEnd - objLiteral.sourceStart + 1);
+
+ org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField[] fields = objLiteral.fields;
+ if (fields != null) {
+ int fieldsLength = fields.length;
+ for (int i = 0; i < fieldsLength; i++) {
+
+ ObjectLiteralField objectLiteralField =convert(fields[i]);
+ objectLiteral.fields().add(objectLiteralField);
+ }
+ }
+
+ if (this.resolveBindings) {
+ recordNodes(objectLiteral, objLiteral);
+ }
+ return objectLiteral;
+ }
+
+ public ObjectLiteralField convert(org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField field) {
+ ObjectLiteralField objectLiteralField = new ObjectLiteralField(this.ast);
+ objectLiteralField.setSourceRange(field.sourceStart, field.sourceEnd - field.sourceStart + 1);
+
+ objectLiteralField.setFieldName( convert(field.fieldName));
+ objectLiteralField.setInitializer( convert(field.initializer));
+ if (this.resolveBindings) {
+ recordNodes(objectLiteralField, field);
+ }
+ return objectLiteralField;
+ }
+
+ public RegularExpressionLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.RegExLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ RegularExpressionLiteral literal = new RegularExpressionLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.internalSetRegularExpression(new String(this.compilationUnitSource, sourceStart, length));
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.ClassLiteralAccess expression) {
+ TypeLiteral typeLiteral = new TypeLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(typeLiteral, expression);
+ }
+ typeLiteral.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ typeLiteral.setType(convertType(expression.type));
+ return typeLiteral;
+ }
+
+ public JavaScriptUnit convert(org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
+ if(unit.compilationResult.recoveryScannerData != null) {
+ RecoveryScanner recoveryScanner = new RecoveryScanner(this.scanner, unit.compilationResult.recoveryScannerData.removeUnused());
+ this.scanner = recoveryScanner;
+ this.docParser.scanner = this.scanner;
+ }
+ this.compilationUnitSource = source;
+ this.compilationUnitSourceLength = source.length;
+ this.scanner.setSource(source, unit.compilationResult);
+ JavaScriptUnit compilationUnit = new JavaScriptUnit(this.ast);
+
+ // Parse comments
+ int[][] comments = unit.comments;
+ if (comments != null) {
+ buildCommentsTable(compilationUnit, comments);
+ }
+
+ // handle the package declaration immediately
+ // There is no node corresponding to the package declaration
+ if (this.resolveBindings) {
+ recordNodes(compilationUnit, unit);
+ }
+ if (unit.currentPackage != null) {
+ PackageDeclaration packageDeclaration = convertPackage(unit);
+ compilationUnit.setPackage(packageDeclaration);
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference[] imports = unit.imports;
+ if (imports != null) {
+ int importLength = imports.length;
+ for (int i = 0; i < importLength; i++) {
+ compilationUnit.imports().add(convertImport(imports[i]));
+ }
+ }
+
+// org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
+// if (types != null) {
+// int typesLength = types.length;
+// for (int i = 0; i < typesLength; i++) {
+// org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration declaration = types[i];
+// if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) {
+// continue;
+// }
+// ASTNode type = convert(declaration);
+// if (type == null) {
+// compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+// } else {
+// compilationUnit.types().add(type);
+// }
+// }
+// }
+ org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement[] statements = unit.statements;
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+// org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration declaration = types[i];
+// if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) {
+// continue;
+// }
+ ProgramElement programElement=statements[i];
+ ASTNode type = null;
+ if (programElement instanceof LocalDeclaration )
+ {
+ checkAndAddMultipleLocalDeclaration(statements, i, compilationUnit.statements());
+
+ }
+ else if (programElement instanceof AbstractMethodDeclaration )
+ {
+ type = convert((AbstractMethodDeclaration)programElement);
+ }
+ else if (programElement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Statement )
+ {
+ type = convert((org.eclipse.wst.jsdt.internal.compiler.ast.Statement )programElement);
+ }
+ else
+ throw new RuntimeException(""); //$NON-NLS-1$
+
+
+ if (type == null) {
+// compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+ } else {
+ compilationUnit.statements().add(type);
+ }
+ }
+ }
+ compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart + 1);
+
+ int problemLength = unit.compilationResult.problemCount;
+ if (problemLength != 0) {
+ CategorizedProblem[] resizedProblems = null;
+ final CategorizedProblem[] problems = unit.compilationResult.getProblems();
+ final int realProblemLength=problems.length;
+ if (realProblemLength == problemLength) {
+ resizedProblems = problems;
+ } else {
+ System.arraycopy(problems, 0, (resizedProblems = new CategorizedProblem[realProblemLength]), 0, realProblemLength);
+ }
+ ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems);
+ compilationUnit.accept(syntaxErrorPropagator);
+ ASTRecoveryPropagator recoveryPropagator =
+ new ASTRecoveryPropagator(resizedProblems, unit.compilationResult.recoveryScannerData);
+ compilationUnit.accept(recoveryPropagator);
+ compilationUnit.setProblems(resizedProblems);
+ }
+ if (this.resolveBindings) {
+ lookupForScopes();
+ }
+ compilationUnit.initCommentMapper(this.scanner);
+ return compilationUnit;
+ }
+
+ public Assignment convert(org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment expression) {
+ Assignment assignment = new Assignment(this.ast);
+ Expression lhs = convert(expression.lhs);
+ assignment.setLeftHandSide(lhs);
+ int start = lhs.getStartPosition();
+ assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+ switch (expression.operator) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.PLUS :
+ assignment.setOperator(Assignment.Operator.PLUS_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MINUS :
+ assignment.setOperator(Assignment.Operator.MINUS_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+ assignment.setOperator(Assignment.Operator.TIMES_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.DIVIDE :
+ assignment.setOperator(Assignment.Operator.DIVIDE_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.AND :
+ assignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.OR :
+ assignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.XOR :
+ assignment.setOperator(Assignment.Operator.BIT_XOR_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.REMAINDER :
+ assignment.setOperator(Assignment.Operator.REMAINDER_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+ assignment.setOperator(Assignment.Operator.LEFT_SHIFT_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+ assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+ assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN);
+ break;
+ }
+ assignment.setRightHandSide(convert(expression.expression));
+ if (this.resolveBindings) {
+ recordNodes(assignment, expression);
+ }
+ return assignment;
+ }
+
+ public ConditionalExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression expression) {
+ ConditionalExpression conditionalExpression = new ConditionalExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(conditionalExpression, expression);
+ }
+ conditionalExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ conditionalExpression.setExpression(convert(expression.condition));
+ conditionalExpression.setThenExpression(convert(expression.valueIfTrue));
+ conditionalExpression.setElseExpression(convert(expression.valueIfFalse));
+ return conditionalExpression;
+ }
+
+ public ContinueStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.ContinueStatement statement) {
+ ContinueStatement continueStatement = new ContinueStatement(this.ast);
+ continueStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ if (statement.label != null) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(statement.label));
+ retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+ continueStatement.setLabel(name);
+ }
+ return continueStatement;
+ }
+
+ public DoStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.DoStatement statement) {
+ DoStatement doStatement = new DoStatement(this.ast);
+ doStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ doStatement.setExpression(convert(statement.condition));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ doStatement.setBody(action);
+ return doStatement;
+ }
+
+ public NumberLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.DoubleLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public EmptyStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.EmptyStatement statement) {
+ EmptyStatement emptyStatement = new EmptyStatement(this.ast);
+ emptyStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ return emptyStatement;
+ }
+
+
+ public EmptyExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.EmptyExpression expression) {
+ EmptyExpression emptyExpression = new EmptyExpression(this.ast);
+ emptyExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return emptyExpression;
+ }
+
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(infixExpression, expression);
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ switch ((expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+ infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+ }
+ return infixExpression;
+
+ }
+
+ public Statement convert(org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall statement) {
+ Statement newStatement;
+ int sourceStart = statement.sourceStart;
+ if (statement.isSuperAccess() || statement.isSuper()) {
+ SuperConstructorInvocation superConstructorInvocation = new SuperConstructorInvocation(this.ast);
+ if (statement.qualification != null) {
+ superConstructorInvocation.setExpression(convert(statement.qualification));
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ superConstructorInvocation.arguments().add(convert(arguments[i]));
+ }
+ }
+ if (statement.typeArguments != null) {
+ if (sourceStart > statement.typeArgumentsSourceStart) {
+ sourceStart = statement.typeArgumentsSourceStart;
+ }
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ superConstructorInvocation.setFlags(superConstructorInvocation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+ superConstructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+ }
+ break;
+ }
+ }
+ newStatement = superConstructorInvocation;
+ } else {
+ ConstructorInvocation constructorInvocation = new ConstructorInvocation(this.ast);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ constructorInvocation.arguments().add(convert(arguments[i]));
+ }
+ }
+ if (statement.typeArguments != null) {
+ if (sourceStart > statement.typeArgumentsSourceStart) {
+ sourceStart = statement.typeArgumentsSourceStart;
+ }
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+ break;
+ case AST.JLS3 :
+ for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+ constructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+ }
+ break;
+ }
+ }
+ if (statement.qualification != null) {
+ // this is an error
+ constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+ }
+ newStatement = constructorInvocation;
+ }
+ newStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(newStatement, statement);
+ }
+ return newStatement;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression) {
+ if (expression==null)
+ return null;
+ if ((expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+ return convertToParenthesizedExpression(expression);
+ }
+ // switch between all types of expression
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.PostfixExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.PostfixExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Assignment) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.Assignment) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ClassLiteralAccess) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ClassLiteralAccess) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FalseLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.FalseLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TrueLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.TrueLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.NullLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.NullLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.DoubleLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.DoubleLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteralMinValue) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteralMinValue) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral) expression);
+ }
+ if (expression instanceof StringLiteralConcatenation) {
+ return convert((StringLiteralConcatenation) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ExtendedStringLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ExtendedStringLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.InstanceOfExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.InstanceOfExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Reference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.Reference) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.RegExLiteral) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.RegExLiteral) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ListExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ListExpression) expression);
+ }
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.EmptyExpression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.EmptyExpression) expression);
+ }
+ return null;
+ }
+
+ public StringLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.ExtendedStringLiteral expression) {
+ expression.computeConstant();
+ StringLiteral literal = new StringLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setLiteralValue(expression.constant.stringValue());
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public BooleanLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.FalseLiteral expression) {
+ final BooleanLiteral literal = new BooleanLiteral(this.ast);
+ literal.setBooleanValue(false);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference reference) {
+ if (reference.receiver.isSuper()) {
+ final SuperFieldAccess superFieldAccess = new SuperFieldAccess(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(superFieldAccess, reference);
+ }
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(reference.token));
+ int sourceStart = (int)(reference.nameSourcePosition>>>32);
+ int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+ simpleName.setSourceRange(sourceStart, length);
+ superFieldAccess.setName(simpleName);
+ if (this.resolveBindings) {
+ recordNodes(simpleName, reference);
+ }
+ superFieldAccess.setSourceRange(reference.receiver.sourceStart, reference.sourceEnd - reference.receiver.sourceStart + 1);
+ return superFieldAccess;
+ } else {
+ final FieldAccess fieldAccess = new FieldAccess(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(fieldAccess, reference);
+ }
+ Expression receiver = convert(reference.receiver);
+ fieldAccess.setExpression(receiver);
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(reference.token));
+ int sourceStart = (int)(reference.nameSourcePosition>>>32);
+ int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+ simpleName.setSourceRange(sourceStart, length);
+ fieldAccess.setName(simpleName);
+ if (this.resolveBindings) {
+ recordNodes(simpleName, reference);
+ }
+ fieldAccess.setSourceRange(receiver.getStartPosition(), reference.sourceEnd - receiver.getStartPosition() + 1);
+ return fieldAccess;
+ }
+ }
+
+ public Statement convert(ForeachStatement statement) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ return createFakeEmptyStatement(statement);
+ case AST.JLS3 :
+ EnhancedForStatement enhancedForStatement = new EnhancedForStatement(this.ast);
+ enhancedForStatement.setParameter(convertToSingleVariableDeclaration(statement.elementVariable));
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression collection = statement.collection;
+ if (collection == null) return null; enhancedForStatement.setExpression(convert(collection));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ enhancedForStatement.setBody(action);
+ int start = statement.sourceStart;
+ int end = statement.sourceEnd;
+ enhancedForStatement.setSourceRange(start, end - start + 1);
+ return enhancedForStatement;
+ default:
+ return createFakeEmptyStatement(statement);
+ }
+ }
+
+ public ForStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.ForStatement statement) {
+ ForStatement forStatement = new ForStatement(this.ast);
+ forStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] initializations = statement.initializations;
+ if (initializations != null) {
+ // we know that we have at least one initialization
+ if (initializations[0] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+ VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) initializations[0]);
+ int initializationsLength = initializations.length;
+ for (int i = 1; i < initializationsLength; i++) {
+ variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)initializations[i]));
+ }
+ if (initializationsLength != 1) {
+ int start = variableDeclarationExpression.getStartPosition();
+ int end = ((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) initializations[initializationsLength - 1]).declarationSourceEnd;
+ variableDeclarationExpression.setSourceRange(start, end - start + 1);
+ }
+ forStatement.initializers().add(variableDeclarationExpression);
+ } else {
+ int initializationsLength = initializations.length;
+ for (int i = 0; i < initializationsLength; i++) {
+ Expression initializer = convertToExpression(initializations[i]);
+ if (initializer != null) {
+ forStatement.initializers().add(initializer);
+ } else {
+ forStatement.setFlags(forStatement.getFlags() | ASTNode.MALFORMED);
+ }
+ }
+ }
+ }
+ if (statement.condition != null) {
+ forStatement.setExpression(convert(statement.condition));
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] increments = statement.increments;
+ if (increments != null) {
+ int incrementsLength = increments.length;
+ for (int i = 0; i < incrementsLength; i++) {
+ forStatement.updaters().add(convertToExpression(increments[i]));
+ }
+ }
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ forStatement.setBody(action);
+ return forStatement;
+ }
+
+
+ public ForInStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.ForInStatement statement) {
+ ForInStatement forInStatement = new ForInStatement(this.ast);
+ forInStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+
+ Statement iterationVariable = convert(statement.iterationVariable);
+ forInStatement.setIterationVariable(iterationVariable);
+
+ Expression collection = convert(statement.collection);
+ forInStatement.setCollection(collection);
+
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ forInStatement.setBody(action);
+ return forInStatement;
+ }
+ public IfStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.IfStatement statement) {
+ IfStatement ifStatement = new IfStatement(this.ast);
+ ifStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ ifStatement.setExpression(convert(statement.condition));
+ final Statement thenStatement = convert(statement.thenStatement);
+ if (thenStatement == null) return null;
+ ifStatement.setThenStatement(thenStatement);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement statement2 = statement.elseStatement;
+ if (statement2 != null) {
+ final Statement elseStatement = convert(statement2);
+ if (elseStatement != null) {
+ ifStatement.setElseStatement(elseStatement);
+ }
+ }
+ return ifStatement;
+ }
+
+ public InstanceofExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.InstanceOfExpression expression) {
+ InstanceofExpression instanceOfExpression = new InstanceofExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(instanceOfExpression, expression);
+ }
+ Expression leftExpression = convert(expression.expression);
+ instanceOfExpression.setLeftOperand(leftExpression);
+ final Type convertType = convertType(expression.type);
+ instanceOfExpression.setRightOperand(convertType);
+ int startPosition = leftExpression.getStartPosition();
+ int sourceEnd = convertType.getStartPosition() + convertType.getLength() - 1;
+ instanceOfExpression.setSourceRange(startPosition, sourceEnd - startPosition + 1);
+ return instanceOfExpression;
+ }
+
+ public NumberLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ final NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public NumberLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteralMinValue expression) {
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ NumberLiteral literal = new NumberLiteral(this.ast);
+ literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(sourceStart, length);
+ removeLeadingAndTrailingCommentsFromLiteral(literal);
+ return literal;
+ }
+
+ public void convert(org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
+ if (bodyDeclaration.getJavadoc() == null) {
+ if (javadoc != null) {
+ if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+ this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+ }
+ Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+ if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+ JSdoc docComment = (JSdoc) comment;
+ if (this.resolveBindings) {
+ recordNodes(docComment, javadoc);
+ // resolve member and method references binding
+ Iterator tags = docComment.tags().listIterator();
+ while (tags.hasNext()) {
+ recordNodes(javadoc, (TagElement) tags.next());
+ }
+ }
+ bodyDeclaration.setJavadoc(docComment);
+ }
+ }
+ }
+ }
+
+ public void convert(org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc javadoc, VariableDeclarationStatement variable) {
+ if (variable.getJavadoc() == null) {
+ if (javadoc != null) {
+ if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+ this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+ }
+ Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+ if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+ JSdoc docComment = (JSdoc) comment;
+ if (this.resolveBindings) {
+ recordNodes(docComment, javadoc);
+ // resolve member and method references binding
+ Iterator tags = docComment.tags().listIterator();
+ while (tags.hasNext()) {
+ recordNodes(javadoc, (TagElement) tags.next());
+ }
+ }
+ variable.setJavadoc(docComment);
+ }
+ }
+ }
+ }
+
+ public void convert(org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc javadoc, PackageDeclaration packageDeclaration) {
+ if (ast.apiLevel == AST.JLS3 && packageDeclaration.getJavadoc() == null) {
+ if (javadoc != null) {
+ if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+ this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+ }
+ Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+ if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+ JSdoc docComment = (JSdoc) comment;
+ if (this.resolveBindings) {
+ recordNodes(docComment, javadoc);
+ // resolve member and method references binding
+ Iterator tags = docComment.tags().listIterator();
+ while (tags.hasNext()) {
+ recordNodes(javadoc, (TagElement) tags.next());
+ }
+ }
+ packageDeclaration.setJavadoc(docComment);
+ }
+ }
+ }
+ }
+
+ public LabeledStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.LabeledStatement statement) {
+ LabeledStatement labeledStatement = new LabeledStatement(this.ast);
+ final int sourceStart = statement.sourceStart;
+ labeledStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+ Statement body = convert(statement.statement);
+ if (body == null) return null;
+ labeledStatement.setBody(body);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(statement.label));
+ name.setSourceRange(sourceStart, statement.labelEnd - sourceStart + 1);
+ labeledStatement.setLabel(name);
+ return labeledStatement;
+ }
+
+ public ListExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.ListExpression expression) {
+ ListExpression listExpression = new ListExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(listExpression, expression);
+ }
+ listExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] expressions = expression.expressions;
+ if (expressions != null) {
+ int length = expressions.length;
+ for (int i = 0; i < length; i++) {
+ Expression expr = convert(expressions[i]);
+ if (this.resolveBindings) {
+ recordNodes(expr, expressions[i]);
+ }
+ listExpression.expressions().add(expr);
+ }
+ }
+ return listExpression;
+ }
+
+ public Expression convert(MessageSend expression) {
+ // will return a FunctionInvocation or a SuperMethodInvocation or
+ Expression expr;
+ int sourceStart = expression.sourceStart;
+ if (expression.isSuperAccess()) {
+ // returns a SuperMethodInvocation
+ final SuperMethodInvocation superMethodInvocation = new SuperMethodInvocation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(superMethodInvocation, expression);
+ }
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(expression.selector));
+ int nameSourceStart = (int) (expression.nameSourcePosition >>> 32);
+ int nameSourceLength = ((int) expression.nameSourcePosition) - nameSourceStart + 1;
+ name.setSourceRange(nameSourceStart, nameSourceLength);
+ if (this.resolveBindings) {
+ recordNodes(name, expression);
+ }
+ superMethodInvocation.setName(name);
+
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null) {
+ int argumentsLength = arguments.length;
+ for (int i = 0; i < argumentsLength; i++) {
+ Expression expri = convert(arguments[i]);
+ if (this.resolveBindings) {
+ recordNodes(expri, arguments[i]);
+ }
+ superMethodInvocation.arguments().add(expri);
+ }
+ }
+ expr = superMethodInvocation;
+ } else {
+ // returns a FunctionInvocation
+ final FunctionInvocation methodInvocation = new FunctionInvocation(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(methodInvocation, expression);
+ }
+ if (expression.selector!=null)
+ {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(expression.selector));
+ int nameSourceStart = (int) (expression.nameSourcePosition >>> 32);
+ int nameSourceLength = ((int) expression.nameSourcePosition) - nameSourceStart + 1;
+ name.setSourceRange(nameSourceStart, nameSourceLength);
+ methodInvocation.setName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, expression);
+ }
+
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+ if (arguments != null) {
+ int argumentsLength = arguments.length;
+ for (int i = 0; i < argumentsLength; i++) {
+ Expression expri = convert(arguments[i]);
+ if (this.resolveBindings) {
+ recordNodes(expri, arguments[i]);
+ }
+ methodInvocation.arguments().add(expri);
+ }
+ }
+ Expression qualifier = null;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression receiver = expression.receiver;
+ if (receiver instanceof MessageSend) {
+ if ((receiver.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+ qualifier = convertToParenthesizedExpression(receiver);
+ } else {
+ qualifier = convert((MessageSend) receiver);
+ }
+ } else {
+ qualifier = convert(receiver);
+ }
+ if (qualifier instanceof Name && this.resolveBindings) {
+ recordNodes(qualifier, receiver);
+ }
+ methodInvocation.setExpression(qualifier);
+ if (qualifier != null) {
+ sourceStart = qualifier.getStartPosition();
+ }
+ expr = methodInvocation;
+ }
+ expr.setSourceRange(sourceStart, expression.sourceEnd - sourceStart + 1);
+ removeTrailingCommentFromExpressionEndingWithAParen(expr);
+ return expr;
+ }
+
+
+ public Name convert(org.eclipse.wst.jsdt.internal.compiler.ast.NameReference reference) {
+ if (reference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference) reference);
+ } else {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference) reference);
+ }
+ }
+
+ public InfixExpression convert(StringLiteralConcatenation expression) {
+ expression.computeConstant();
+ final InfixExpression infixExpression = new InfixExpression(this.ast);
+ infixExpression.setOperator(InfixExpression.Operator.PLUS);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] stringLiterals = expression.literals;
+ infixExpression.setLeftOperand(convert(stringLiterals[0]));
+ infixExpression.setRightOperand(convert(stringLiterals[1]));
+ for (int i = 2; i < expression.counter; i++) {
+ infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+ }
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ infixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return infixExpression;
+ }
+
+
+ public NullLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.NullLiteral expression) {
+ final NullLiteral literal = new NullLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public UndefinedLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral expression) {
+ final UndefinedLiteral literal = new UndefinedLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression expression) {
+ InfixExpression infixExpression = new InfixExpression(this.ast);
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ final int expressionOperatorID = (expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+ if (expression.left instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression
+ && ((expression.left.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+ // create an extended string literal equivalent => use the extended operands list
+ infixExpression.extendedOperands().add(convert(expression.right));
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression leftOperand = expression.left;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression rightOperand = null;
+ do {
+ rightOperand = ((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+ if ((((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+ && ((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+ || ((rightOperand instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression
+ && ((rightOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+ && ((rightOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+ List extendedOperands = infixExpression.extendedOperands();
+ InfixExpression temp = new InfixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ Expression leftSide = convert(leftOperand);
+ temp.setLeftOperand(leftSide);
+ temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+ int size = extendedOperands.size();
+ for (int i = 0; i < size - 1; i++) {
+ Expression expr = temp;
+ temp = new InfixExpression(this.ast);
+
+ if (this.resolveBindings) {
+ this.recordNodes(temp, expression);
+ }
+ temp.setLeftOperand(expr);
+ temp.setOperator(getOperatorFor(expressionOperatorID));
+ temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+ }
+ infixExpression = temp;
+ for (int i = 0; i < size; i++) {
+ Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+ temp.setRightOperand(extendedOperand);
+ int startPosition = temp.getLeftOperand().getStartPosition();
+ temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+ if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+ temp = (InfixExpression) temp.getLeftOperand();
+ }
+ }
+ int startPosition = infixExpression.getLeftOperand().getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ if (this.resolveBindings) {
+ this.recordNodes(infixExpression, expression);
+ }
+ return infixExpression;
+ }
+ infixExpression.extendedOperands().add(0, convert(rightOperand));
+ leftOperand = ((org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+ } while (leftOperand instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+ Expression leftExpression = convert(leftOperand);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+ Expression leftExpression = convert(expression.left);
+ infixExpression.setLeftOperand(leftExpression);
+ infixExpression.setRightOperand(convert(expression.right));
+ infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+ int startPosition = leftExpression.getStartPosition();
+ infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+ return infixExpression;
+ }
+
+ public PostfixExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.PostfixExpression expression) {
+ final PostfixExpression postfixExpression = new PostfixExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(postfixExpression, expression);
+ }
+ postfixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ postfixExpression.setOperand(convert(expression.lhs));
+ switch (expression.operator) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.PLUS :
+ postfixExpression.setOperator(PostfixExpression.Operator.INCREMENT);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MINUS :
+ postfixExpression.setOperator(PostfixExpression.Operator.DECREMENT);
+ break;
+ }
+ return postfixExpression;
+ }
+
+ public PrefixExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression expression) {
+ final PrefixExpression prefixExpression = new PrefixExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(prefixExpression, expression);
+ }
+ prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ prefixExpression.setOperand(convert(expression.lhs));
+ switch (expression.operator) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.PLUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.INCREMENT);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MINUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.DECREMENT);
+ break;
+ }
+ return prefixExpression;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression allocation) {
+ final ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation(this.ast);
+ if (allocation.enclosingInstance != null) {
+ classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
+ }
+ if (allocation.member != null) {
+ classInstanceCreation.setMember(convert(allocation.member));
+ }
+ if (allocation.type!=null)
+ {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ classInstanceCreation.internalSetName(convert(allocation.type));
+ break;
+ case AST.JLS3 :
+ classInstanceCreation.setType(convertType(allocation.type));
+ }
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
+ if (arguments != null) {
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ Expression argument = convert(arguments[i]);
+ if (this.resolveBindings) {
+ recordNodes(argument, arguments[i]);
+ }
+ classInstanceCreation.arguments().add(argument);
+ }
+ }
+ if (allocation.anonymousType != null) {
+ int declarationSourceStart = allocation.sourceStart;
+ classInstanceCreation.setSourceRange(declarationSourceStart, allocation.anonymousType.bodyEnd - declarationSourceStart + 1);
+ final AnonymousClassDeclaration anonymousClassDeclaration = new AnonymousClassDeclaration(this.ast);
+ int start = retrieveStartBlockPosition(allocation.anonymousType.sourceEnd, allocation.anonymousType.bodyEnd);
+ anonymousClassDeclaration.setSourceRange(start, allocation.anonymousType.bodyEnd - start + 1);
+ classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
+ buildBodyDeclarations(allocation.anonymousType, anonymousClassDeclaration);
+ if (this.resolveBindings) {
+ recordNodes(classInstanceCreation, allocation.anonymousType);
+ recordNodes(anonymousClassDeclaration, allocation.anonymousType);
+ anonymousClassDeclaration.resolveBinding();
+ }
+ return classInstanceCreation;
+ } else {
+ final int start = allocation.sourceStart;
+ classInstanceCreation.setSourceRange(start, allocation.sourceEnd - start + 1);
+ if (this.resolveBindings) {
+ recordNodes(classInstanceCreation, allocation);
+ }
+ removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+ return classInstanceCreation;
+ }
+ }
+
+ public Name convert(org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference nameReference) {
+ return setQualifiedNameNameAndSourceRanges(nameReference.tokens, nameReference.sourcePositions, nameReference);
+ }
+
+ public ThisExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedThisReference reference) {
+ final ThisExpression thisExpression = new ThisExpression(this.ast);
+ thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+ thisExpression.setQualifier(convert(reference.qualification));
+ if (this.resolveBindings) {
+ recordNodes(thisExpression, reference);
+ recordPendingThisExpressionScopeResolution(thisExpression);
+ }
+ return thisExpression;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.Reference reference) {
+ if (reference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.NameReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.NameReference) reference);
+ }
+ if (reference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference) reference);
+ }
+ if (reference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference) reference);
+ }
+ if (reference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference) reference);
+ }
+ return null; // cannot be reached
+ }
+
+ public ReturnStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement statement) {
+ final ReturnStatement returnStatement = new ReturnStatement(this.ast);
+ returnStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ if (statement.expression != null) {
+ returnStatement.setExpression(convert(statement.expression));
+ }
+ return returnStatement;
+ }
+
+ public SimpleName convert(org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference nameReference) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(nameReference.token));
+ if (this.resolveBindings) {
+ recordNodes(name, nameReference);
+ }
+ name.setSourceRange(nameReference.sourceStart, nameReference.sourceEnd - nameReference.sourceStart + 1);
+ return name;
+ }
+
+ public Statement convert(org.eclipse.wst.jsdt.internal.compiler.ast.Statement statement) {
+ if (statement instanceof ForeachStatement) {
+ return convert((ForeachStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+ return convertToVariableDeclarationStatement((org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Block) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.Block) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.BreakStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.BreakStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ContinueStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ContinueStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.DoStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.DoStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.EmptyStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.EmptyStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ForStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ForStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ForInStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ForInStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.IfStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.IfStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LabeledStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.LabeledStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+ ASTNode result = convert((org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) statement);
+ if (result == null) {
+ return createFakeEmptyStatement(statement);
+ }
+ TypeDeclaration typeDeclaration = (TypeDeclaration) result;
+ TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+ typeDeclarationStatement.setDeclaration(typeDeclaration);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ TypeDeclaration typeDecl = typeDeclarationStatement.internalGetTypeDeclaration();
+ typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+ break;
+ case AST.JLS3 :
+ AbstractTypeDeclaration typeDeclAST3 = typeDeclarationStatement.getDeclaration();
+ typeDeclarationStatement.setSourceRange(typeDeclAST3.getStartPosition(), typeDeclAST3.getLength());
+ break;
+ }
+ return typeDeclarationStatement;
+
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.WhileStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.WhileStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.WithStatement) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.WithStatement) statement);
+ }
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression statement2 = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) statement;
+ final Expression expr = convert( statement2);
+ final ExpressionStatement stmt = new ExpressionStatement(this.ast);
+ stmt.setExpression(expr);
+ int sourceStart = expr.getStartPosition();
+ int sourceEnd = statement2.statementEnd;
+ if (sourceEnd==-1)
+ sourceEnd=statement2.sourceEnd;
+ stmt.setSourceRange(sourceStart, sourceEnd - sourceStart + 1);
+ return stmt;
+ }
+ return createFakeEmptyStatement(statement);
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral expression) {
+ if (expression instanceof StringLiteralConcatenation) {
+ return convert((StringLiteralConcatenation) expression);
+ }
+ int length = expression.sourceEnd - expression.sourceStart + 1;
+ int sourceStart = expression.sourceStart;
+ StringLiteral literal = new StringLiteral(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.internalSetEscapedValue(new String(this.compilationUnitSource, sourceStart, length));
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public SwitchStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement statement) {
+ SwitchStatement switchStatement = new SwitchStatement(this.ast);
+ switchStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ switchStatement.setExpression(convert(statement.expression));
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] statements = statement.statements;
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ if (statements[i] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+ checkAndAddMultipleLocalDeclaration(statements, i, switchStatement.statements());
+ } else {
+ final Statement currentStatement = convert(statements[i]);
+ if (currentStatement != null) {
+ switchStatement.statements().add(currentStatement);
+ }
+ }
+ }
+ }
+ return switchStatement;
+ }
+
+ public Expression convert(org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference reference) {
+ if (reference.isImplicitThis()) {
+ // There is no source associated with an implicit this
+ return null;
+ } else if (reference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedThisReference) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedThisReference) reference);
+ } else {
+ ThisExpression thisExpression = new ThisExpression(this.ast);
+ thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(thisExpression, reference);
+ recordPendingThisExpressionScopeResolution(thisExpression);
+ }
+ return thisExpression;
+ }
+ }
+
+ public ThrowStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement statement) {
+ final ThrowStatement throwStatement = new ThrowStatement(this.ast);
+ throwStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ throwStatement.setExpression(convert(statement.exception));
+ return throwStatement;
+ }
+
+ public BooleanLiteral convert(org.eclipse.wst.jsdt.internal.compiler.ast.TrueLiteral expression) {
+ final BooleanLiteral literal = new BooleanLiteral(this.ast);
+ literal.setBooleanValue(true);
+ if (this.resolveBindings) {
+ this.recordNodes(literal, expression);
+ }
+ literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ return literal;
+ }
+
+ public TryStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement statement) {
+ final TryStatement tryStatement = new TryStatement(this.ast);
+ tryStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+
+ tryStatement.setBody(convert(statement.tryBlock));
+ org.eclipse.wst.jsdt.internal.compiler.ast.Argument[] catchArguments = statement.catchArguments;
+ if (catchArguments != null) {
+ int catchArgumentsLength = catchArguments.length;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Block[] catchBlocks = statement.catchBlocks;
+ int start = statement.tryBlock.sourceEnd;
+ for (int i = 0; i < catchArgumentsLength; i++) {
+ CatchClause catchClause = new CatchClause(this.ast);
+ int catchClauseSourceStart = retrieveStartingCatchPosition(start, catchArguments[i].sourceStart);
+ catchClause.setSourceRange(catchClauseSourceStart, catchBlocks[i].sourceEnd - catchClauseSourceStart + 1);
+ catchClause.setBody(convert(catchBlocks[i]));
+ catchClause.setException(convert(catchArguments[i]));
+ tryStatement.catchClauses().add(catchClause);
+ start = catchBlocks[i].sourceEnd;
+ }
+ }
+ if (statement.finallyBlock != null) {
+ tryStatement.setFinally(convert(statement.finallyBlock));
+ }
+ return tryStatement;
+ }
+
+ public ASTNode convert(org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ checkCanceled();
+ TypeDeclaration typeDecl = new TypeDeclaration(this.ast);
+ if (typeDeclaration.modifiersSourceStart != -1) {
+ setModifiers(typeDecl, typeDeclaration);
+ }
+ final SimpleName typeName = new SimpleName(this.ast);
+ typeName.internalSetIdentifier(new String(typeDeclaration.name));
+ typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+ typeDecl.setName(typeName);
+ typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+
+ // need to set the superclass and super interfaces here since we cannot distinguish them at
+ // the type references level.
+ if (typeDeclaration.superclass != null) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ typeDecl.internalSetSuperclass(convert(typeDeclaration.superclass));
+ break;
+ case AST.JLS3 :
+ typeDecl.setSuperclassType(convertType(typeDeclaration.superclass));
+ break;
+ }
+ }
+
+ buildBodyDeclarations(typeDeclaration, typeDecl);
+ if (this.resolveBindings) {
+ recordNodes(typeDecl, typeDeclaration);
+ recordNodes(typeName, typeDeclaration);
+ typeDecl.resolveBinding();
+ }
+ return typeDecl;
+ }
+
+ public Name convert(org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference typeReference) {
+ char[][] typeName = typeReference.getTypeName();
+ int length = typeName.length;
+ if (length > 1) {
+ // QualifiedName
+ org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference qualifiedTypeReference = (org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference) typeReference;
+ final long[] positions = qualifiedTypeReference.sourcePositions;
+ return setQualifiedNameNameAndSourceRanges(typeName, positions, typeReference);
+ } else {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(typeName[0]));
+ name.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd - typeReference.sourceStart + 1);
+ name.index = 1;
+ if (this.resolveBindings) {
+ recordNodes(name, typeReference);
+ }
+ return name;
+ }
+ }
+
+ public PrefixExpression convert(org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression expression) {
+ final PrefixExpression prefixExpression = new PrefixExpression(this.ast);
+ if (this.resolveBindings) {
+ this.recordNodes(prefixExpression, expression);
+ }
+ prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ prefixExpression.setOperand(convert(expression.expression));
+ switch ((expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.PLUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.PLUS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MINUS :
+ prefixExpression.setOperator(PrefixExpression.Operator.MINUS);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.NOT :
+ prefixExpression.setOperator(PrefixExpression.Operator.NOT);
+ break;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.TWIDDLE :
+ prefixExpression.setOperator(PrefixExpression.Operator.COMPLEMENT);
+ }
+ return prefixExpression;
+ }
+
+ public WhileStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.WhileStatement statement) {
+ final WhileStatement whileStatement = new WhileStatement(this.ast);
+ whileStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ whileStatement.setExpression(convert(statement.condition));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ whileStatement.setBody(action);
+ return whileStatement;
+ }
+
+
+ public WithStatement convert(org.eclipse.wst.jsdt.internal.compiler.ast.WithStatement statement) {
+ final WithStatement withStatement = new WithStatement(this.ast);
+ withStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+ withStatement.setExpression(convert(statement.condition));
+ final Statement action = convert(statement.action);
+ if (action == null) return null;
+ withStatement.setBody(action);
+ return withStatement;
+ }
+
+ public ImportDeclaration convertImport(org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference importReference) {
+ final ImportDeclaration importDeclaration = new ImportDeclaration(this.ast);
+ final boolean onDemand = (importReference.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OnDemand) != 0;
+ final char[][] tokens = importReference.tokens;
+ int length = importReference.tokens.length;
+ final long[] positions = importReference.sourcePositions;
+ if (length > 1) {
+ importDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
+ } else if(length == 1) {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(tokens[0]));
+ final int start = (int)(positions[0]>>>32);
+ final int end = (int)(positions[0] & 0xFFFFFFFF);
+ name.setSourceRange(start, end - start + 1);
+ name.index = 1;
+ importDeclaration.setName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, importReference);
+ }
+ }
+ boolean isFile=(importReference.bits&org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.IsFileImport)!=0;
+ importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+ importDeclaration.setOnDemand(onDemand && !isFile);
+ importDeclaration.setIsFileImport(isFile);
+
+ if (this.resolveBindings) {
+ recordNodes(importDeclaration, importReference);
+ }
+ return importDeclaration;
+ }
+
+ public PackageDeclaration convertPackage(org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
+ final PackageDeclaration packageDeclaration = new PackageDeclaration(this.ast);
+ final char[][] tokens = importReference.tokens;
+ final int length = importReference.tokens.length;
+ long[] positions = importReference.sourcePositions;
+ if (length > 1) {
+ packageDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
+ } else {
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(tokens[0]));
+ int start = (int)(positions[0]>>>32);
+ int end = (int)(positions[length - 1] & 0xFFFFFFFF);
+ name.setSourceRange(start, end - start + 1);
+ name.index = 1;
+ packageDeclaration.setName(name);
+ if (this.resolveBindings) {
+ recordNodes(name, compilationUnitDeclaration);
+ }
+ }
+ packageDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+
+ if (this.resolveBindings) {
+ recordNodes(packageDeclaration, importReference);
+ }
+ // Set javadoc
+ convert(compilationUnitDeclaration.javadoc, packageDeclaration);
+ return packageDeclaration;
+ }
+
+ public Expression convertToExpression(org.eclipse.wst.jsdt.internal.compiler.ast.Statement statement) {
+ if (statement instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Expression) {
+ return convert((org.eclipse.wst.jsdt.internal.compiler.ast.Expression) statement);
+ } else {
+ return null;
+ }
+ }
+
+ protected FieldDeclaration convertToFieldDeclaration(org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration fieldDecl) {
+ VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(fieldDecl);
+ final FieldDeclaration fieldDeclaration = new FieldDeclaration(this.ast);
+ fieldDeclaration.fragments().add(variableDeclarationFragment);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, fieldDecl);
+ variableDeclarationFragment.resolveBinding();
+ }
+ fieldDeclaration.setSourceRange(fieldDecl.declarationSourceStart, fieldDecl.declarationEnd - fieldDecl.declarationSourceStart + 1);
+ Type type = convertType(fieldDecl.type,fieldDecl.inferredType);
+ setTypeForField(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions());
+// setModifiers(fieldDeclaration, fieldDecl);
+ convert(fieldDecl.javadoc, fieldDeclaration);
+ return fieldDeclaration;
+ }
+
+ public ParenthesizedExpression convertToParenthesizedExpression(org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression) {
+ final ParenthesizedExpression parenthesizedExpression = new ParenthesizedExpression(this.ast);
+ if (this.resolveBindings) {
+ recordNodes(parenthesizedExpression, expression);
+ }
+ parenthesizedExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+ adjustSourcePositionsForParent(expression);
+ trimWhiteSpacesAndComments(expression);
+ // decrement the number of parenthesis
+ int numberOfParenthesis = (expression.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) >> org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+ expression.bits &= ~org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedMASK;
+ expression.bits |= (numberOfParenthesis - 1) << org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+ parenthesizedExpression.setExpression(convert(expression));
+ return parenthesizedExpression;
+ }
+
+ public Type convertToType(org.eclipse.wst.jsdt.internal.compiler.ast.NameReference reference) {
+ Name name = convert(reference);
+ final SimpleType type = new SimpleType(this.ast);
+ type.setName(name);
+ type.setSourceRange(name.getStartPosition(), name.getLength());
+ if (this.resolveBindings) {
+ this.recordNodes(type, reference);
+ }
+ return type;
+ }
+
+ protected VariableDeclarationExpression convertToVariableDeclarationExpression(org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+ final VariableDeclarationExpression variableDeclarationExpression = new VariableDeclarationExpression(this.ast);
+ variableDeclarationExpression.fragments().add(variableDeclarationFragment);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, localDeclaration);
+ }
+ variableDeclarationExpression.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+ Type type = convertType(localDeclaration.type,localDeclaration.inferredType);
+ setTypeForVariableDeclarationExpression(variableDeclarationExpression, type, variableDeclarationFragment.getExtraDimensions());
+ if (localDeclaration.modifiersSourceStart != -1) {
+ setModifiers(variableDeclarationExpression, localDeclaration);
+ }
+ return variableDeclarationExpression;
+ }
+
+ protected SingleVariableDeclaration convertToSingleVariableDeclaration(LocalDeclaration localDeclaration) {
+ final SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+ setModifiers(variableDecl, localDeclaration);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(localDeclaration.name));
+ int start = localDeclaration.sourceStart;
+ int nameEnd = localDeclaration.sourceEnd;
+ name.setSourceRange(start, nameEnd - start + 1);
+ variableDecl.setName(name);
+ final int extraDimensions = retrieveExtraDimension(nameEnd + 1, localDeclaration.type.sourceEnd);
+ variableDecl.setExtraDimensions(extraDimensions);
+ Type type = convertType(localDeclaration.type,localDeclaration.inferredType);
+ int typeEnd = type.getStartPosition() + type.getLength() - 1;
+ int rightEnd = Math.max(typeEnd, localDeclaration.declarationSourceEnd);
+ /*
+ * There is extra work to do to set the proper type positions
+ * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+ */
+ setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+ variableDecl.setSourceRange(localDeclaration.declarationSourceStart, rightEnd - localDeclaration.declarationSourceStart + 1);
+ if (this.resolveBindings) {
+ recordNodes(name, localDeclaration);
+ recordNodes(variableDecl, localDeclaration);
+ variableDecl.resolveBinding();
+ }
+ return variableDecl;
+ }
+
+ protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration fieldDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = new VariableDeclarationFragment(this.ast);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(fieldDeclaration.name));
+ name.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd - fieldDeclaration.sourceStart + 1);
+ variableDeclarationFragment.setName(name);
+ int start = fieldDeclaration.sourceEnd;
+ if (fieldDeclaration.initialization != null) {
+ final Expression expression = convert(fieldDeclaration.initialization);
+ variableDeclarationFragment.setInitializer(expression);
+ start = expression.getStartPosition() + expression.getLength();
+ }
+ int end = retrievePositionBeforeNextCommaOrSemiColon(start, fieldDeclaration.declarationSourceEnd);
+ if (end == -1) {
+ variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.declarationSourceEnd - fieldDeclaration.sourceStart + 1);
+ variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+ } else {
+ variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, end - fieldDeclaration.sourceStart + 1);
+ }
+ variableDeclarationFragment.setExtraDimensions(retrieveExtraDimension(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd ));
+ if (this.resolveBindings) {
+ recordNodes(name, fieldDeclaration);
+ recordNodes(variableDeclarationFragment, fieldDeclaration);
+ variableDeclarationFragment.resolveBinding();
+ }
+ return variableDeclarationFragment;
+ }
+
+ protected VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = new VariableDeclarationFragment(this.ast);
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(localDeclaration.name));
+ name.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
+ variableDeclarationFragment.setName(name);
+ int start = localDeclaration.sourceEnd;
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression initialization = localDeclaration.initialization;
+ boolean hasInitialization = initialization != null;
+ if (hasInitialization) {
+ final Expression expression = convert(initialization);
+ variableDeclarationFragment.setInitializer(expression);
+ start = expression.getStartPosition() + expression.getLength();
+ }
+ int end = retrievePositionBeforeNextCommaOrSemiColon(start, localDeclaration.declarationSourceEnd);
+ if (end == -1) {
+ if (hasInitialization) {
+ // the initiazation sourceEnd is modified during convert(initialization)
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=128961
+ end = start - 1;
+ } else {
+ end = localDeclaration.sourceEnd;
+ }
+ }
+ variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, end - localDeclaration.sourceStart + 1);
+ variableDeclarationFragment.setExtraDimensions(retrieveExtraDimension(localDeclaration.sourceEnd + 1, this.compilationUnitSourceLength));
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, localDeclaration);
+ recordNodes(name, localDeclaration);
+ variableDeclarationFragment.resolveBinding();
+ }
+ return variableDeclarationFragment;
+ }
+
+ protected VariableDeclarationStatement convertToVariableDeclarationStatement(org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+ final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+ final VariableDeclarationStatement variableDeclarationStatement = new VariableDeclarationStatement(this.ast);
+ variableDeclarationStatement.fragments().add(variableDeclarationFragment);
+ if (this.resolveBindings) {
+ recordNodes(variableDeclarationFragment, localDeclaration);
+ }
+ variableDeclarationStatement.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+ if (localDeclaration.type!=null)
+ {
+ Type type = convertType(localDeclaration.type,localDeclaration.inferredType);
+ setTypeForVariableDeclarationStatement(variableDeclarationStatement, type, variableDeclarationFragment.getExtraDimensions());
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration local = localDeclaration;
+ while (local.nextLocal!=null) {
+ variableDeclarationStatement.fragments().add(convertToVariableDeclarationFragment(local.nextLocal));
+ local=(org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration)local.nextLocal;
+ }
+
+ if (localDeclaration.modifiersSourceStart != -1) {
+ setModifiers(variableDeclarationStatement, localDeclaration);
+ }
+ convert(localDeclaration.javadoc, variableDeclarationStatement);
+ return variableDeclarationStatement;
+ }
+
+ public Type convertType(TypeReference typeReference) {
+ return convertType(typeReference,null);
+ }
+ public Type convertType(TypeReference typeReference, org.eclipse.wst.jsdt.core.infer.InferredType inferredType) {
+ if (typeReference==null)
+ {
+ InferredType newType=new InferredType(this.ast);
+ newType.setSourceRange(-1,0);
+ if (inferredType!=null)
+ {
+ newType.type=new String(inferredType.getName());
+ if (this.resolveBindings)
+ recordNodes(newType, inferredType);
+ }
+ return newType;
+ }
+ Type type = null;
+ int sourceStart = -1;
+ int length = 0;
+ int dimensions = typeReference.dimensions();
+ if (typeReference instanceof org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference) {
+ // this is either an ArrayTypeReference or a SingleTypeReference
+ char[] name = ((org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference) typeReference).getTypeName()[0];
+ sourceStart = typeReference.sourceStart;
+ length = typeReference.sourceEnd - typeReference.sourceStart + 1;
+ // need to find out if this is an array type of primitive types or not
+ if (isPrimitiveType(name)) {
+ int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+ if (end == -1) {
+ end = sourceStart + length - 1;
+ }
+ final PrimitiveType primitiveType = new PrimitiveType(this.ast);
+ primitiveType.setPrimitiveTypeCode(getPrimitiveTypeCode(name));
+ primitiveType.setSourceRange(sourceStart, end - sourceStart + 1);
+ type = primitiveType;
+ } else {
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(name));
+ // we need to search for the starting position of the first brace in order to set the proper length
+ // PR http://dev.eclipse.org/bugs/show_bug.cgi?id=10759
+ int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+ if (end == -1) {
+ end = sourceStart + length - 1;
+ }
+ simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+ final SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(simpleName);
+ type = simpleType;
+ type.setSourceRange(sourceStart, end - sourceStart + 1);
+ type = simpleType;
+ if (this.resolveBindings) {
+ this.recordNodes(simpleName, typeReference);
+ }
+ }
+ if (dimensions != 0) {
+ type = this.ast.newArrayType(type, dimensions);
+ type.setSourceRange(sourceStart, length);
+ ArrayType subarrayType = (ArrayType) type;
+ int index = dimensions - 1;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ int end = retrieveProperRightBracketPosition(index, sourceStart);
+ subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+ index--;
+ }
+ if (this.resolveBindings) {
+ // store keys for inner types
+ completeRecord((ArrayType) type, typeReference);
+ }
+ }
+ } else {
+ char[][] name = ((org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+ int nameLength = name.length;
+ long[] positions = ((org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference) typeReference).sourcePositions;
+ sourceStart = (int)(positions[0]>>>32);
+ length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+ final Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+ final SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(qualifiedName);
+ type = simpleType;
+ type.setSourceRange(sourceStart, length);
+
+ length = typeReference.sourceEnd - sourceStart + 1;
+ if (dimensions != 0) {
+ type = this.ast.newArrayType(type, dimensions);
+ if (this.resolveBindings) {
+ completeRecord((ArrayType) type, typeReference);
+ }
+ int end = retrieveEndOfDimensionsPosition(sourceStart+length, this.compilationUnitSourceLength);
+ if (end != -1) {
+ type.setSourceRange(sourceStart, end - sourceStart + 1);
+ } else {
+ type.setSourceRange(sourceStart, length);
+ }
+ ArrayType subarrayType = (ArrayType) type;
+ int index = dimensions - 1;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ end = retrieveProperRightBracketPosition(index, sourceStart);
+ subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+ index--;
+ }
+ }
+ }
+ if (this.resolveBindings) {
+ this.recordNodes(type, typeReference);
+ }
+ return type;
+ }
+
+ protected Comment createComment(int[] positions) {
+ // Create comment node
+ Comment comment = null;
+ int start = positions[0];
+ int end = positions[1];
+ if (positions[1]>0) { // jsdoc comments have positive end position
+ JSdoc docComment = this.docParser.parse(positions);
+ if (docComment == null) return null;
+ comment = docComment;
+ } else {
+ end = -end;
+ if (positions[0] == 0) { // we cannot know without testing chars again
+ if (this.docParser.scanner.source[1] == '/') {
+ comment = new LineComment(this.ast);
+ } else {
+ comment = new BlockComment(this.ast);
+ }
+ }
+ else if (positions[0]>0) { // Block comment have positive start position
+ comment = new BlockComment(this.ast);
+ } else { // Line comment have negative start and end position
+ start = -start;
+ comment = new LineComment(this.ast);
+ }
+ comment.setSourceRange(start, end - start);
+ }
+ return comment;
+ }
+
+ protected Statement createFakeEmptyStatement(org.eclipse.wst.jsdt.internal.compiler.ast.Statement statement) {
+ if (statement == null) return null;
+ EmptyStatement emptyStatement = new EmptyStatement(this.ast);
+ emptyStatement.setFlags(emptyStatement.getFlags() | ASTNode.MALFORMED);
+ int start = statement.sourceStart;
+ int end = statement.sourceEnd;
+ emptyStatement.setSourceRange(start, end - start + 1);
+ return emptyStatement;
+ }
+ /**
+ * @return a new modifier
+ */
+ private Modifier createModifier(ModifierKeyword keyword) {
+ final Modifier modifier = new Modifier(this.ast);
+ modifier.setKeyword(keyword);
+ int start = this.scanner.getCurrentTokenStartPosition();
+ int end = this.scanner.getCurrentTokenEndPosition();
+ modifier.setSourceRange(start, end - start + 1);
+ return modifier;
+ }
+
+ protected InfixExpression.Operator getOperatorFor(int operatorID) {
+ switch (operatorID) {
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+ return InfixExpression.Operator.EQUALS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+ return InfixExpression.Operator.LESS_EQUALS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+ return InfixExpression.Operator.GREATER_EQUALS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+ return InfixExpression.Operator.NOT_EQUALS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+ return InfixExpression.Operator.LEFT_SHIFT;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+ return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+ return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.OR_OR :
+ return InfixExpression.Operator.CONDITIONAL_OR;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.AND_AND :
+ return InfixExpression.Operator.CONDITIONAL_AND;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.PLUS :
+ return InfixExpression.Operator.PLUS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MINUS :
+ return InfixExpression.Operator.MINUS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.REMAINDER :
+ return InfixExpression.Operator.REMAINDER;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.XOR :
+ return InfixExpression.Operator.XOR;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.AND :
+ return InfixExpression.Operator.AND;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+ return InfixExpression.Operator.TIMES;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.OR :
+ return InfixExpression.Operator.OR;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.DIVIDE :
+ return InfixExpression.Operator.DIVIDE;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.GREATER :
+ return InfixExpression.Operator.GREATER;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.LESS :
+ return InfixExpression.Operator.LESS;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.INSTANCEOF :
+ return InfixExpression.Operator.INSTANCEOF;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.IN :
+ return InfixExpression.Operator.IN;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL_EQUAL :
+ return InfixExpression.Operator.EQUAL_EQUAL_EQUAL;
+ case org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds.NOT_EQUAL_EQUAL :
+ return InfixExpression.Operator.NOT_EQUAL_EQUAL;
+ }
+ return null;
+ }
+
+ protected PrimitiveType.Code getPrimitiveTypeCode(char[] name) {
+ switch(name[0]) {
+ case 'i' :
+ if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+ return PrimitiveType.INT;
+ }
+ break;
+ case 'l' :
+ if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+ return PrimitiveType.LONG;
+ }
+ break;
+ case 'd' :
+ if (name.length == 6
+ && name[1] == 'o'
+ && name[2] == 'u'
+ && name[3] == 'b'
+ && name[4] == 'l'
+ && name[5] == 'e') {
+ return PrimitiveType.DOUBLE;
+ }
+ break;
+ case 'f' :
+ if (name.length == 5
+ && name[1] == 'l'
+ && name[2] == 'o'
+ && name[3] == 'a'
+ && name[4] == 't') {
+ return PrimitiveType.FLOAT;
+ }
+ break;
+ case 'b' :
+ if (name.length == 4
+ && name[1] == 'y'
+ && name[2] == 't'
+ && name[3] == 'e') {
+ return PrimitiveType.BYTE;
+ } else
+ if (name.length == 7
+ && name[1] == 'o'
+ && name[2] == 'o'
+ && name[3] == 'l'
+ && name[4] == 'e'
+ && name[5] == 'a'
+ && name[6] == 'n') {
+ return PrimitiveType.BOOLEAN;
+ }
+ break;
+ case 'c' :
+ if (name.length == 4
+ && name[1] == 'h'
+ && name[2] == 'a'
+ && name[3] == 'r') {
+ return PrimitiveType.CHAR;
+ }
+ break;
+ case 's' :
+ if (name.length == 5
+ && name[1] == 'h'
+ && name[2] == 'o'
+ && name[3] == 'r'
+ && name[4] == 't') {
+ return PrimitiveType.SHORT;
+ }
+ break;
+ case 'v' :
+ if (name.length == 4
+ && name[1] == 'o'
+ && name[2] == 'i'
+ && name[3] == 'd') {
+ return PrimitiveType.VOID;
+ }
+ }
+ return null; // cannot be reached
+ }
+
+ protected boolean isPrimitiveType(char[] name) {
+ switch(name[0]) {
+ case 'i' :
+ if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+ return true;
+ }
+ return false;
+ case 'l' :
+ if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+ return true;
+ }
+ return false;
+ case 'd' :
+ if (name.length == 6
+ && name[1] == 'o'
+ && name[2] == 'u'
+ && name[3] == 'b'
+ && name[4] == 'l'
+ && name[5] == 'e') {
+ return true;
+ }
+ return false;
+ case 'f' :
+ if (name.length == 5
+ && name[1] == 'l'
+ && name[2] == 'o'
+ && name[3] == 'a'
+ && name[4] == 't') {
+ return true;
+ }
+ return false;
+ case 'b' :
+ if (name.length == 4
+ && name[1] == 'y'
+ && name[2] == 't'
+ && name[3] == 'e') {
+ return true;
+ } else
+ if (name.length == 7
+ && name[1] == 'o'
+ && name[2] == 'o'
+ && name[3] == 'l'
+ && name[4] == 'e'
+ && name[5] == 'a'
+ && name[6] == 'n') {
+ return true;
+ }
+ return false;
+ case 'c' :
+ if (name.length == 4
+ && name[1] == 'h'
+ && name[2] == 'a'
+ && name[3] == 'r') {
+ return true;
+ }
+ return false;
+ case 's' :
+ if (name.length == 5
+ && name[1] == 'h'
+ && name[2] == 'o'
+ && name[3] == 'r'
+ && name[4] == 't') {
+ return true;
+ }
+ return false;
+ case 'v' :
+ if (name.length == 4
+ && name[1] == 'o'
+ && name[2] == 'i'
+ && name[3] == 'd') {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ private void lookupForScopes() {
+ if (this.pendingNameScopeResolution != null) {
+ for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) {
+ Name name = (Name) iterator.next();
+ this.ast.getBindingResolver().recordScope(name, lookupScope(name));
+ }
+ }
+ if (this.pendingThisExpressionScopeResolution != null) {
+ for (Iterator iterator = this.pendingThisExpressionScopeResolution.iterator(); iterator.hasNext(); ) {
+ ThisExpression thisExpression = (ThisExpression) iterator.next();
+ this.ast.getBindingResolver().recordScope(thisExpression, lookupScope(thisExpression));
+ }
+ }
+
+ }
+
+ private BlockScope lookupScope(ASTNode node) {
+ ASTNode currentNode = node;
+ while(currentNode != null
+ &&!(currentNode instanceof FunctionDeclaration)
+ && !(currentNode instanceof Initializer)
+ && !(currentNode instanceof FieldDeclaration)) {
+ currentNode = currentNode.getParent();
+ }
+ if (currentNode == null) {
+ return null;
+ }
+ if (currentNode instanceof Initializer) {
+ Initializer initializer = (Initializer) currentNode;
+ while(!(currentNode instanceof AbstractTypeDeclaration)) {
+ currentNode = currentNode.getParent();
+ }
+ if (currentNode instanceof TypeDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ if ((initializer.getModifiers() & Modifier.STATIC) != 0) {
+ return typeDecl.staticInitializerScope;
+ } else {
+ return typeDecl.initializerScope;
+ }
+ }
+ } else if (currentNode instanceof FieldDeclaration) {
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) currentNode;
+ while(!(currentNode instanceof AbstractTypeDeclaration)) {
+ currentNode = currentNode.getParent();
+ }
+ if (currentNode instanceof TypeDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDecl = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ if ((fieldDeclaration.getModifiers() & Modifier.STATIC) != 0) {
+ return typeDecl.staticInitializerScope;
+ } else {
+ return typeDecl.initializerScope;
+ }
+ }
+ }
+ AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+ return abstractMethodDeclaration.scope;
+ }
+
+ protected void recordName(Name name, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode compilerNode) {
+ if (compilerNode != null) {
+ recordNodes(name, compilerNode);
+ if (compilerNode instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference typeRef = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) compilerNode;
+ if (name.isQualifiedName()) {
+ SimpleName simpleName = null;
+ while (name.isQualifiedName()) {
+ simpleName = ((QualifiedName) name).getName();
+ recordNodes(simpleName, typeRef);
+ name = ((QualifiedName) name).getQualifier();
+ recordNodes(name, typeRef);
+ }
+ }
+ }
+ }
+ }
+
+ protected void recordNodes(ASTNode node, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode oldASTNode) {
+ this.ast.getBindingResolver().store(node, oldASTNode);
+ }
+
+ protected void recordNodes(org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc javadoc, TagElement tagElement) {
+ Iterator fragments = tagElement.fragments().listIterator();
+ while (fragments.hasNext()) {
+ ASTNode node = (ASTNode) fragments.next();
+ if (node.getNodeType() == ASTNode.MEMBER_REF) {
+ MemberRef memberRef = (MemberRef) node;
+ Name name = memberRef.getName();
+ // get compiler node and record nodes
+ int start = name.getStartPosition();
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
+ if (compilerNode!= null) {
+ recordNodes(name, compilerNode);
+ recordNodes(node, compilerNode);
+ }
+ // Replace qualifier to have all nodes recorded
+ if (memberRef.getQualifier() != null) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference typeRef = null;
+ if (compilerNode instanceof JavadocFieldReference) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = ((JavadocFieldReference)compilerNode).receiver;
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) {
+ typeRef = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) expression;
+ }
+ }
+ else if (compilerNode instanceof JavadocMessageSend) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = ((JavadocMessageSend)compilerNode).receiver;
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) {
+ typeRef = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) expression;
+ }
+ }
+ if (typeRef != null) {
+ recordName(memberRef.getQualifier(), typeRef);
+ }
+ }
+ } else if (node.getNodeType() == ASTNode.FUNCTION_REF) {
+ FunctionRef methodRef = (FunctionRef) node;
+ Name name = methodRef.getName();
+ // get method name start position
+ int start = methodRef.getStartPosition();
+ this.scanner.resetTo(start, start + name.getStartPosition()+name.getLength());
+ int token;
+ try {
+ nextToken: while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF && token != TerminalTokens.TokenNameLPAREN) {
+ if (token == TerminalTokens.TokenNameERROR && this.scanner.currentCharacter == '#') {
+ start = this.scanner.getCurrentTokenEndPosition()+1;
+ break nextToken;
+ }
+ }
+ }
+ catch(InvalidInputException e) {
+ // ignore
+ }
+ // get compiler node and record nodes
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
+ // record nodes
+ if (compilerNode != null) {
+ recordNodes(methodRef, compilerNode);
+ // get type ref
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference typeRef = null;
+ if (compilerNode instanceof org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression) {
+ typeRef = ((org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression)compilerNode).type;
+ if (typeRef != null) recordNodes(name, compilerNode);
+ }
+ else if (compilerNode instanceof org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = ((org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend)compilerNode).receiver;
+ if (expression instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) {
+ typeRef = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference) expression;
+ }
+ recordNodes(name, compilerNode);
+ }
+ // record name and qualifier
+ if (typeRef != null && methodRef.getQualifier() != null) {
+ recordName(methodRef.getQualifier(), typeRef);
+ }
+ }
+ // Resolve parameters
+ Iterator parameters = methodRef.parameters().listIterator();
+ while (parameters.hasNext()) {
+ FunctionRefParameter param = (FunctionRefParameter) parameters.next();
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) javadoc.getNodeStartingAt(param.getStartPosition());
+ if (expression != null) {
+ recordNodes(param, expression);
+ if (expression instanceof JavadocArgumentExpression) {
+ JavadocArgumentExpression argExpr = (JavadocArgumentExpression) expression;
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference typeRef = argExpr.argument.type;
+ if (this.ast.apiLevel >= AST.JLS3) param.setVarargs(argExpr.argument.isVarArgs());
+ recordNodes(param.getType(), typeRef);
+ if (param.getType().isSimpleType()) {
+ recordName(((SimpleType)param.getType()).getName(), typeRef);
+ } else if (param.getType().isArrayType()) {
+ Type type = ((ArrayType) param.getType()).getElementType();
+ recordNodes(type, typeRef);
+ if (type.isSimpleType()) {
+ recordName(((SimpleType)type).getName(), typeRef);
+ }
+ }
+ }
+ }
+ }
+ } else if (node.getNodeType() == ASTNode.SIMPLE_NAME ||
+ node.getNodeType() == ASTNode.QUALIFIED_NAME) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(node.getStartPosition());
+ recordName((Name) node, compilerNode);
+ } else if (node.getNodeType() == ASTNode.TAG_ELEMENT) {
+ // resolve member and method references binding
+ recordNodes(javadoc, (TagElement) node);
+ }
+ }
+ }
+ protected void recordPendingNameScopeResolution(Name name) {
+ if (this.pendingNameScopeResolution == null) {
+ this.pendingNameScopeResolution = new HashSet();
+ }
+ this.pendingNameScopeResolution.add(name);
+ }
+
+ protected void recordPendingThisExpressionScopeResolution(ThisExpression thisExpression) {
+ if (this.pendingThisExpressionScopeResolution == null) {
+ this.pendingThisExpressionScopeResolution = new HashSet();
+ }
+ this.pendingThisExpressionScopeResolution.add(thisExpression);
+ }
+
+ /**
+ * Remove whitespaces and comments before and after the expression.
+ */
+ private void trimWhiteSpacesAndComments(org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression) {
+ int start = expression.sourceStart;
+ int end = expression.sourceEnd;
+ int token;
+ int trimLeftPosition = expression.sourceStart;
+ int trimRightPosition = expression.sourceEnd;
+ boolean first = true;
+ Scanner removeBlankScanner = this.ast.scanner;
+ try {
+ removeBlankScanner.setSource(this.compilationUnitSource);
+ removeBlankScanner.resetTo(start, end);
+ while (true) {
+ token = removeBlankScanner.getNextToken();
+ switch (token) {
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ if (first) {
+ trimLeftPosition = removeBlankScanner.currentPosition;
+ }
+ break;
+ case TerminalTokens.TokenNameWHITESPACE :
+ if (first) {
+ trimLeftPosition = removeBlankScanner.currentPosition;
+ }
+ break;
+ case TerminalTokens.TokenNameEOF :
+ expression.sourceStart = trimLeftPosition;
+ expression.sourceEnd = trimRightPosition;
+ return;
+ default :
+ /*
+ * if we find something else than a whitespace or a comment,
+ * then we reset the trimRigthPosition to the expression
+ * source end.
+ */
+ trimRightPosition = removeBlankScanner.currentPosition - 1;
+ first = false;
+ }
+ }
+ } catch (InvalidInputException e){
+ // ignore
+ }
+ }
+
+ /**
+ * Remove potential trailing comment by settings the source end on the closing parenthesis
+ */
+ protected void removeLeadingAndTrailingCommentsFromLiteral(ASTNode node) {
+ int start = node.getStartPosition();
+ this.scanner.resetTo(start, start + node.getLength());
+ int token;
+ int startPosition = -1;
+ try {
+ while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameIntegerLiteral :
+ case TerminalTokens.TokenNameFloatingPointLiteral :
+ case TerminalTokens.TokenNameLongLiteral :
+ case TerminalTokens.TokenNameDoubleLiteral :
+ case TerminalTokens.TokenNameCharacterLiteral :
+ case TerminalTokens.TokenNameRegExLiteral :
+ if (startPosition == -1) {
+ startPosition = this.scanner.startPosition;
+ }
+ int end = this.scanner.currentPosition;
+ node.setSourceRange(startPosition, end - startPosition);
+ return;
+ case TerminalTokens.TokenNameMINUS :
+ startPosition = this.scanner.startPosition;
+ break;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Remove potential trailing comment by settings the source end on the closing parenthesis
+ */
+ protected void removeTrailingCommentFromExpressionEndingWithAParen(ASTNode node) {
+ int start = node.getStartPosition();
+ this.scanner.resetTo(start, start + node.getLength());
+ int token;
+ int parenCounter = 0;
+ try {
+ while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLPAREN :
+ parenCounter++;
+ break;
+ case TerminalTokens.TokenNameRPAREN :
+ parenCounter--;
+ if (parenCounter == 0) {
+ int end = this.scanner.currentPosition - 1;
+ node.setSourceRange(start, end - start + 1);
+ }
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * This method is used to retrieve the end position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveClosingAngleBracketPosition(int start) {
+ this.scanner.resetTo(start, this.compilationUnitSourceLength);
+ this.scanner.returnOnlyGreater = true;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameGREATER:
+ return this.scanner.currentPosition - 1;
+ default:
+ return start;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ this.scanner.returnOnlyGreater = false;
+ return start;
+ }
+
+ /**
+ * This method is used to set the right end position for expression
+ * statement. The actual AST nodes don't include the trailing semicolon.
+ * This method fixes the length of the corresponding node.
+ */
+ protected void retrieveColonPosition(ASTNode node) {
+ int start = node.getStartPosition();
+ int length = node.getLength();
+ int end = start + length;
+ this.scanner.resetTo(end, this.compilationUnitSourceLength);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameCOLON:
+ node.setSourceRange(start, this.scanner.currentPosition - start);
+ return;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+// /**
+// * This method is used to retrieve the start position of the Ellipsis
+// */
+// protected int retrieveEllipsisStartPosition(int start, int end) {
+// this.scanner.resetTo(start, end);
+// try {
+// int token;
+// while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+// switch(token) {
+// case TerminalTokens.TokenNameELLIPSIS:
+// return this.scanner.startPosition - 1;
+// }
+// }
+// } catch(InvalidInputException e) {
+// // ignore
+// }
+// return -1;
+//
+// }
+ /**
+ * This method is used to retrieve the end position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveEndBlockPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ int count = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACE://110
+ count++;
+ break;
+ case TerminalTokens.TokenNameRBRACE://95
+ count--;
+ if (count == 0) {
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ protected int retrieveSemiColonPosition(Expression node) {
+ int start = node.getStartPosition();
+ int length = node.getLength();
+ int end = start + length;
+ this.scanner.resetTo(end, this.compilationUnitSourceLength);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameSEMICOLON:
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the ending position for a type declaration when the dimension is right after the type
+ * name.
+ * For example:
+ * int[] i; => return 5, but int i[] => return -1;
+ * @return int the dimension found
+ */
+ protected int retrieveEndOfDimensionsPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ int foundPosition = -1;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACKET:
+ case TerminalTokens.TokenNameCOMMENT_BLOCK:
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+ case TerminalTokens.TokenNameCOMMENT_LINE:
+ break;
+ case TerminalTokens.TokenNameRBRACKET://166
+ foundPosition = this.scanner.currentPosition - 1;
+ break;
+ default:
+ return foundPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return foundPosition;
+ }
+
+ /**
+ * This method is used to retrieve the position just before the left bracket.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveEndOfElementTypeNamePosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameIdentifier:
+ case TerminalTokens.TokenNamebyte:
+ case TerminalTokens.TokenNamechar:
+ case TerminalTokens.TokenNamedouble:
+ case TerminalTokens.TokenNamefloat:
+ case TerminalTokens.TokenNameint:
+ case TerminalTokens.TokenNamelong:
+ case TerminalTokens.TokenNameshort:
+ case TerminalTokens.TokenNameboolean:
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the position after the right parenthesis.
+ * @return int the position found
+ */
+ protected int retrieveEndOfRightParenthesisPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRPAREN:
+ return this.scanner.currentPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the array dimension declared after the
+ * name of a local or a field declaration.
+ * For example:
+ * int i, j[] = null, k[][] = {{}};
+ * It should return 0 for i, 1 for j and 2 for k.
+ * @return int the dimension found
+ */
+ protected int retrieveExtraDimension(int start, int end) {
+ this.scanner.resetTo(start, end);
+ int dimensions = 0;
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACKET:
+ case TerminalTokens.TokenNameCOMMENT_BLOCK:
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+ case TerminalTokens.TokenNameCOMMENT_LINE:
+ break;
+ case TerminalTokens.TokenNameRBRACKET://166
+ dimensions++;
+ break;
+ default:
+ return dimensions;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return dimensions;
+ }
+
+ protected void retrieveIdentifierAndSetPositions(int start, int end, Name name) {
+ this.scanner.resetTo(start, end);
+ int token;
+ try {
+ while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ if (token == TerminalTokens.TokenNameIdentifier) {
+ int startName = this.scanner.startPosition;
+ int endName = this.scanner.currentPosition - 1;
+ name.setSourceRange(startName, endName - startName + 1);
+ return;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * This method is used to retrieve the start position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveIdentifierEndPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameIdentifier://110
+ return this.scanner.getCurrentTokenEndPosition();
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve position before the next comma or semi-colon.
+ * @return int the position found.
+ */
+ protected int retrievePositionBeforeNextCommaOrSemiColon(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ int balance = 0;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACE :
+ balance++;
+ break;
+ case TerminalTokens.TokenNameRBRACE :
+ balance --;
+ break;
+ case TerminalTokens.TokenNameCOMMA :
+ if (balance == 0) return this.scanner.startPosition - 1;
+ break;
+ case TerminalTokens.TokenNameSEMICOLON :
+ return this.scanner.startPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ protected int retrieveProperRightBracketPosition(int bracketNumber, int start) {
+ this.scanner.resetTo(start, this.compilationUnitSourceLength);
+ try {
+ int token, count = 0;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACKET:
+ count++;
+ if (count == bracketNumber) {
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve position before the next right brace or semi-colon.
+ * @return int the position found.
+ */
+ protected int retrieveRightBraceOrSemiColonPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACE :
+ return this.scanner.currentPosition - 1;
+ case TerminalTokens.TokenNameSEMICOLON :
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve position before the next right brace or semi-colon.
+ * @return int the position found.
+ */
+ protected int retrieveRightBrace(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACE :
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the position of the right bracket.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveRightBracketPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACKET:
+ return this.scanner.currentPosition - 1;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+
+
+ /**
+ * This method is used to retrieve the start position of the block.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveStartBlockPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameLBRACE://110
+ return this.scanner.startPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ /**
+ * This method is used to retrieve the starting position of the catch keyword.
+ * @return int the dimension found, -1 if none
+ */
+ protected int retrieveStartingCatchPosition(int start, int end) {
+ this.scanner.resetTo(start, end);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNamecatch://225
+ return this.scanner.startPosition;
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ return -1;
+ }
+
+ public void setAST(AST ast) {
+ this.ast = ast;
+ this.docParser = new DocCommentParser(this.ast, this.scanner, this.insideComments);
+ }
+
+ /**
+ * @param bodyDeclaration
+ */
+ protected void setModifiers(BodyDeclaration bodyDeclaration) {
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ bodyDeclaration.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+
+
+ /**
+ * @param fieldDeclaration
+ * @param fieldDecl
+ */
+ protected void setModifiers(FieldDeclaration fieldDeclaration, org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ fieldDeclaration.internalSetModifiers(fieldDecl.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(fieldDecl.declarationSourceStart, fieldDecl.sourceStart);
+ this.setModifiers(fieldDeclaration);
+ }
+ }
+
+ /**
+ * @param initializer
+ * @param oldInitializer
+ */
+ protected void setModifiers(Initializer initializer, org.eclipse.wst.jsdt.internal.compiler.ast.Initializer oldInitializer) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL:
+ initializer.internalSetModifiers(oldInitializer.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(oldInitializer.declarationSourceStart, oldInitializer.bodyStart);
+ this.setModifiers(initializer);
+ }
+ }
+ /**
+ * @param methodDecl
+ * @param methodDeclaration
+ */
+ protected void setModifiers(FunctionDeclaration methodDecl, AbstractMethodDeclaration methodDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDecl.internalSetModifiers(methodDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ break;
+ case AST.JLS3 :
+ if (methodDeclaration.sourceStart>methodDeclaration.declarationSourceStart)
+ {
+ this.scanner.resetTo(methodDeclaration.declarationSourceStart, methodDeclaration.sourceStart);
+ this.setModifiers(methodDecl);
+ }
+ }
+ }
+
+ /**
+ * @param variableDecl
+ * @param argument
+ */
+ protected void setModifiers(SingleVariableDeclaration variableDecl, Argument argument) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.internalSetModifiers(argument.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(argument.declarationSourceStart, argument.sourceStart);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDecl.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ protected void setModifiers(SingleVariableDeclaration variableDecl, LocalDeclaration localDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ variableDecl.internalSetModifiers(localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDecl.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * @param typeDecl
+ * @param typeDeclaration
+ */
+ protected void setModifiers(TypeDeclaration typeDecl, org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ int modifiers = typeDeclaration.modifiers;
+ modifiers &= ExtraCompilerModifiers.AccJustFlag;
+ typeDecl.internalSetModifiers(modifiers);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+ this.setModifiers(typeDecl);
+ }
+ }
+
+ /**
+ * @param variableDeclarationExpression
+ * @param localDeclaration
+ */
+ protected void setModifiers(VariableDeclarationExpression variableDeclarationExpression, LocalDeclaration localDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ int modifiers = localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag;
+ modifiers &= ~ExtraCompilerModifiers.AccBlankFinal;
+ variableDeclarationExpression.internalSetModifiers(modifiers);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDeclarationExpression.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * @param variableDeclarationStatement
+ * @param localDeclaration
+ */
+ protected void setModifiers(VariableDeclarationStatement variableDeclarationStatement, LocalDeclaration localDeclaration) {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ int modifiers = localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag;
+ modifiers &= ~ExtraCompilerModifiers.AccBlankFinal;
+ variableDeclarationStatement.internalSetModifiers(modifiers);
+ break;
+ case AST.JLS3 :
+ this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+ try {
+ int token;
+ while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ IExtendedModifier modifier = null;
+ switch(token) {
+ case TerminalTokens.TokenNameabstract:
+ modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamepublic:
+ modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamestatic:
+ modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprotected:
+ modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameprivate:
+ modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamefinal:
+ modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamenative:
+ modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamesynchronized:
+ modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+ break;
+ case TerminalTokens.TokenNametransient:
+ modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+ break;
+ case TerminalTokens.TokenNamevolatile:
+ modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+ break;
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ break;
+ default :
+ return;
+ }
+ if (modifier != null) {
+ variableDeclarationStatement.modifiers().add(modifier);
+ }
+ }
+ } catch(InvalidInputException e) {
+ // ignore
+ }
+ }
+ }
+
+ protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node) {
+ int length = typeName.length;
+ final SimpleName firstToken = new SimpleName(this.ast);
+ firstToken.internalSetIdentifier(new String(typeName[0]));
+ firstToken.index = 1;
+ int start0 = (int)(positions[0]>>>32);
+ int start = start0;
+ int end = (int)(positions[0] & 0xFFFFFFFF);
+ firstToken.setSourceRange(start, end - start + 1);
+ final SimpleName secondToken = new SimpleName(this.ast);
+ secondToken.internalSetIdentifier(new String(typeName[1]));
+ secondToken.index = 2;
+ start = (int)(positions[1]>>>32);
+ end = (int)(positions[1] & 0xFFFFFFFF);
+ secondToken.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName = new QualifiedName(this.ast);
+ qualifiedName.setQualifier(firstToken);
+ qualifiedName.setName(secondToken);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordNodes(firstToken, node);
+ recordNodes(secondToken, node);
+ recordPendingNameScopeResolution(firstToken);
+ recordPendingNameScopeResolution(secondToken);
+ }
+ qualifiedName.index = 2;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ SimpleName newPart = null;
+ for (int i = 2; i < length; i++) {
+ newPart = new SimpleName(this.ast);
+ newPart.internalSetIdentifier(new String(typeName[i]));
+ newPart.index = i + 1;
+ start = (int)(positions[i]>>>32);
+ end = (int)(positions[i] & 0xFFFFFFFF);
+ newPart.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName2 = new QualifiedName(this.ast);
+ qualifiedName2.setQualifier(qualifiedName);
+ qualifiedName2.setName(newPart);
+ qualifiedName = qualifiedName2;
+ qualifiedName.index = newPart.index;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordNodes(newPart, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordPendingNameScopeResolution(newPart);
+ }
+ }
+ QualifiedName name = qualifiedName;
+ if (this.resolveBindings) {
+ recordNodes(name, node);
+ recordPendingNameScopeResolution(name);
+ }
+ return name;
+ }
+
+ protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, int endingIndex, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node) {
+ int length = endingIndex + 1;
+ final SimpleName firstToken = new SimpleName(this.ast);
+ firstToken.internalSetIdentifier(new String(typeName[0]));
+ firstToken.index = 1;
+ int start0 = (int)(positions[0]>>>32);
+ int start = start0;
+ int end = (int) positions[0];
+ firstToken.setSourceRange(start, end - start + 1);
+ final SimpleName secondToken = new SimpleName(this.ast);
+ secondToken.internalSetIdentifier(new String(typeName[1]));
+ secondToken.index = 2;
+ start = (int)(positions[1]>>>32);
+ end = (int) positions[1];
+ secondToken.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName = new QualifiedName(this.ast);
+ qualifiedName.setQualifier(firstToken);
+ qualifiedName.setName(secondToken);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordNodes(firstToken, node);
+ recordNodes(secondToken, node);
+ recordPendingNameScopeResolution(firstToken);
+ recordPendingNameScopeResolution(secondToken);
+ }
+ qualifiedName.index = 2;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ SimpleName newPart = null;
+ for (int i = 2; i < length; i++) {
+ newPart = new SimpleName(this.ast);
+ newPart.internalSetIdentifier(new String(typeName[i]));
+ newPart.index = i + 1;
+ start = (int)(positions[i]>>>32);
+ end = (int) positions[i];
+ newPart.setSourceRange(start, end - start + 1);
+ QualifiedName qualifiedName2 = new QualifiedName(this.ast);
+ qualifiedName2.setQualifier(qualifiedName);
+ qualifiedName2.setName(newPart);
+ qualifiedName = qualifiedName2;
+ qualifiedName.index = newPart.index;
+ qualifiedName.setSourceRange(start0, end - start0 + 1);
+ if (this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordNodes(newPart, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ recordPendingNameScopeResolution(newPart);
+ }
+ }
+ if (newPart == null && this.resolveBindings) {
+ recordNodes(qualifiedName, node);
+ recordPendingNameScopeResolution(qualifiedName);
+ }
+ return qualifiedName;
+ }
+
+
+ protected void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ fieldDeclaration.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ fieldDeclaration.setType(subarrayType);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ fieldDeclaration.setType(type);
+ }
+ } else {
+ if (type.isArrayType()) {
+ // update positions of the component types of the array type
+ int dimensions = ((ArrayType) type).getDimensions();
+ updateInnerPositions(type, dimensions);
+ }
+ fieldDeclaration.setType(type);
+ }
+ }
+
+ protected void setTypeForMethodDeclaration(FunctionDeclaration methodDeclaration, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(elementType);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(elementType);
+ break;
+ }
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(subarrayType);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(subarrayType);
+ break;
+ }
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(type);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(type);
+ break;
+ }
+ }
+ } else {
+ switch(this.ast.apiLevel) {
+ case AST.JLS2_INTERNAL :
+ methodDeclaration.internalSetReturnType(type);
+ break;
+ case AST.JLS3 :
+ methodDeclaration.setReturnType2(type);
+ break;
+ }
+ }
+ }
+
+ protected void setTypeForSingleVariableDeclaration(SingleVariableDeclaration singleVariableDeclaration, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ singleVariableDeclaration.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ singleVariableDeclaration.setType(subarrayType);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ singleVariableDeclaration.setType(type);
+ }
+ } else {
+ singleVariableDeclaration.setType(type);
+ }
+ }
+
+ protected void setTypeForVariableDeclarationExpression(VariableDeclarationExpression variableDeclarationExpression, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ variableDeclarationExpression.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ variableDeclarationExpression.setType(subarrayType);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ variableDeclarationExpression.setType(type);
+ }
+ } else {
+ variableDeclarationExpression.setType(type);
+ }
+ }
+
+ protected void setTypeForVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, Type type, int extraDimension) {
+ if (extraDimension != 0) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ int remainingDimensions = arrayType.getDimensions() - extraDimension;
+ if (remainingDimensions == 0) {
+ // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+ Type elementType = arrayType.getElementType();
+ // cut the child loose from its parent (without creating garbage)
+ elementType.setParent(null, null);
+ this.ast.getBindingResolver().updateKey(type, elementType);
+ variableDeclarationStatement.setType(elementType);
+ } else {
+ int start = type.getStartPosition();
+ ArrayType subarrayType = arrayType;
+ int index = extraDimension;
+ while (index > 0) {
+ subarrayType = (ArrayType) subarrayType.getComponentType();
+ index--;
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subarrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subarrayType.setParent(null, null);
+ updateInnerPositions(subarrayType, remainingDimensions);
+ variableDeclarationStatement.setType(subarrayType);
+ this.ast.getBindingResolver().updateKey(type, subarrayType);
+ }
+ } else {
+ variableDeclarationStatement.setType(type);
+ }
+ } else {
+ variableDeclarationStatement.setType(type);
+ }
+ }
+
+ protected void updateInnerPositions(Type type, int dimensions) {
+ if (dimensions > 1) {
+ // need to set positions for intermediate array type see 42839
+ int start = type.getStartPosition();
+ Type currentComponentType = ((ArrayType) type).getComponentType();
+ int searchedDimension = dimensions - 1;
+ int rightBracketEndPosition = start;
+ while (currentComponentType.isArrayType()) {
+ rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start);
+ currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
+ currentComponentType = ((ArrayType) currentComponentType).getComponentType();
+ searchedDimension--;
+ }
+ }
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTMatcher.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTMatcher.java
new file mode 100644
index 0000000..a5de253
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTMatcher.java
@@ -0,0 +1,2083 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Concrete superclass and default implementation of an AST subtree matcher.
+ *
+ * For example, to compute whether two ASTs subtrees are structurally
+ * isomorphic, use n1.subtreeMatch(new ASTMatcher(), n2)
where
+ * n1
and n2
are the AST root nodes of the subtrees.
+ *
+ *
+ * For each different concrete AST node type T there is a
+ * public boolean match(T node, Object other)
method
+ * that matches the given node against another object (typically another
+ * AST node, although this is not essential). The default implementations
+ * provided by this class tests whether the other object is a node of the
+ * same type with structurally isomorphic child subtrees. For nodes with
+ * list-valued properties, the child nodes within the list are compared in
+ * order. For nodes with multiple properties, the child nodes are compared
+ * in the order that most closely corresponds to the lexical reading order
+ * of the source program. For instance, for a type declaration node, the
+ * child ordering is: name, superclass, superinterfaces, and body
+ * declarations.
+ *
+ *
+ * Subclasses may override (extend or reimplement) some or all of the
+ * match
methods in order to define more specialized subtree
+ * matchers.
+ *
+ *
+ * @see org.eclipse.wst.jsdt.core.dom.ASTNode#subtreeMatch(ASTMatcher, Object)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ASTMatcher {
+
+ /**
+ * Indicates whether doc tags should be matched.
+ */
+ private boolean matchDocTags;
+
+ /**
+ * Creates a new AST matcher instance.
+ *
+ * For backwards compatibility, the matcher ignores tag
+ * elements below doc comments by default. Use
+ * {@link #ASTMatcher(boolean) ASTMatcher(true)}
+ * for a matcher that compares doc tags by default.
+ *
+ */
+ public ASTMatcher() {
+ this(false);
+ }
+
+ /**
+ * Creates a new AST matcher instance.
+ *
+ * @param matchDocTags true
if doc comment tags are
+ * to be compared by default, and false
otherwise
+ * @see #match(JSdoc,Object)
+ */
+ public ASTMatcher(boolean matchDocTags) {
+ this.matchDocTags = matchDocTags;
+ }
+
+ /**
+ * Returns whether the given lists of AST nodes match pair wise according
+ * to ASTNode.subtreeMatch
.
+ *
+ * Note that this is a convenience method, useful for writing recursive
+ * subtree matchers.
+ *
+ *
+ * @param list1 the first list of AST nodes
+ * (element type: ASTNode
)
+ * @param list2 the second list of AST nodes
+ * (element type: ASTNode
)
+ * @return true
if the lists have the same number of elements
+ * and match pair-wise according to ASTNode.subtreeMatch
+ * @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
+ */
+ public final boolean safeSubtreeListMatch(List list1, List list2) {
+ int size1 = list1.size();
+ int size2 = list2.size();
+ if (size1 != size2) {
+ return false;
+ }
+ for (Iterator it1 = list1.iterator(), it2 = list2.iterator(); it1.hasNext();) {
+ ASTNode n1 = (ASTNode) it1.next();
+ ASTNode n2 = (ASTNode) it2.next();
+ if (!n1.subtreeMatch(this, n2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given nodes match according to
+ * AST.subtreeMatch
. Returns false
if one or
+ * the other of the nodes are null
. Returns true
+ * if both nodes are null
.
+ *
+ * Note that this is a convenience method, useful for writing recursive
+ * subtree matchers.
+ *
+ *
+ * @param node1 the first AST node, or null
; must be an
+ * instance of ASTNode
+ * @param node2 the second AST node, or null
; must be an
+ * instance of ASTNode
+ * @return true
if the nodes match according
+ * to AST.subtreeMatch
or both are null
, and
+ * false
otherwise
+ * @see ASTNode#subtreeMatch(ASTMatcher, Object)
+ */
+ public final boolean safeSubtreeMatch(Object node1, Object node2) {
+ if (node1 == null && node2 == null) {
+ return true;
+ }
+ if (node1 == null || node2 == null) {
+ return false;
+ }
+ // N.B. call subtreeMatch even node1==node2!=null
+ return ((ASTNode) node1).subtreeMatch(this, node2);
+ }
+
+ /**
+ * Returns whether the given objects are equal according to
+ * equals
. Returns false
if either
+ * node is null
.
+ *
+ * @param o1 the first object, or null
+ * @param o2 the second object, or null
+ * @return true
if the nodes are equal according to
+ * equals
or both null
, and
+ * false
otherwise
+ */
+ public static boolean safeEquals(Object o1, Object o2) {
+ if (o1 == o2) {
+ return true;
+ }
+ if (o1 == null || o2 == null) {
+ return false;
+ }
+ return o1.equals(o2);
+ }
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(AnonymousClassDeclaration node, Object other) {
+ if (!(other instanceof AnonymousClassDeclaration)) {
+ return false;
+ }
+ AnonymousClassDeclaration o = (AnonymousClassDeclaration) other;
+ return safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ArrayAccess node, Object other) {
+ if (!(other instanceof ArrayAccess)) {
+ return false;
+ }
+ ArrayAccess o = (ArrayAccess) other;
+ return (
+ safeSubtreeMatch(node.getArray(), o.getArray())
+ && safeSubtreeMatch(node.getIndex(), o.getIndex()));
+ }
+
+ /**
+ * Returns whether the given node and the other object object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ArrayCreation node, Object other) {
+ if (!(other instanceof ArrayCreation)) {
+ return false;
+ }
+ ArrayCreation o = (ArrayCreation) other;
+ return (
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.dimensions(), o.dimensions())
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ArrayInitializer node, Object other) {
+ if (!(other instanceof ArrayInitializer)) {
+ return false;
+ }
+ ArrayInitializer o = (ArrayInitializer) other;
+ return safeSubtreeListMatch(node.expressions(), o.expressions());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ArrayType node, Object other) {
+ if (!(other instanceof ArrayType)) {
+ return false;
+ }
+ ArrayType o = (ArrayType) other;
+ return safeSubtreeMatch(node.getComponentType(), o.getComponentType());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(Assignment node, Object other) {
+ if (!(other instanceof Assignment)) {
+ return false;
+ }
+ Assignment o = (Assignment) other;
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getLeftHandSide(), o.getLeftHandSide())
+ && safeSubtreeMatch(node.getRightHandSide(), o.getRightHandSide()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(Block node, Object other) {
+ if (!(other instanceof Block)) {
+ return false;
+ }
+ Block o = (Block) other;
+ return safeSubtreeListMatch(node.statements(), o.statements());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type. Subclasses may override
+ * this method as needed.
+ *
+ * Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(BlockComment node, Object other) {
+ if (!(other instanceof BlockComment)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(BooleanLiteral node, Object other) {
+ if (!(other instanceof BooleanLiteral)) {
+ return false;
+ }
+ BooleanLiteral o = (BooleanLiteral) other;
+ return node.booleanValue() == o.booleanValue();
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(BreakStatement node, Object other) {
+ if (!(other instanceof BreakStatement)) {
+ return false;
+ }
+ BreakStatement o = (BreakStatement) other;
+ return safeSubtreeMatch(node.getLabel(), o.getLabel());
+ }
+
+ public boolean match(FunctionExpression node, Object other) {
+ if (!(other instanceof FunctionExpression)) {
+ return false;
+ }
+ FunctionExpression o = (FunctionExpression) other;
+ return
+ safeSubtreeMatch(node.getMethod(), o.getMethod());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(CatchClause node, Object other) {
+ if (!(other instanceof CatchClause)) {
+ return false;
+ }
+ CatchClause o = (CatchClause) other;
+ return (
+ safeSubtreeMatch(node.getException(), o.getException())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(CharacterLiteral node, Object other) {
+ if (!(other instanceof CharacterLiteral)) {
+ return false;
+ }
+ CharacterLiteral o = (CharacterLiteral) other;
+ return safeEquals(node.getEscapedValue(), o.getEscapedValue());
+ }
+
+ public boolean match(RegularExpressionLiteral node, Object other) {
+ if (!(other instanceof CharacterLiteral)) {
+ return false;
+ }
+ RegularExpressionLiteral o = (RegularExpressionLiteral) other;
+ return safeEquals(node.getRegularExpression(), o.getRegularExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ClassInstanceCreation node, Object other) {
+ if (!(other instanceof ClassInstanceCreation)) {
+ return false;
+ }
+ ClassInstanceCreation o = (ClassInstanceCreation) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (!safeSubtreeMatch(node.internalGetName(), o.internalGetName())) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getType(), o.getType())) {
+ return false;
+ }
+ }
+ return
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getMember(), o.getMember())
+ && safeSubtreeListMatch(node.arguments(), o.arguments())
+ && safeSubtreeMatch(
+ node.getAnonymousClassDeclaration(),
+ o.getAnonymousClassDeclaration());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(JavaScriptUnit node, Object other) {
+ if (!(other instanceof JavaScriptUnit)) {
+ return false;
+ }
+ JavaScriptUnit o = (JavaScriptUnit) other;
+ return (
+ safeSubtreeMatch(node.getPackage(), o.getPackage())
+ && safeSubtreeListMatch(node.imports(), o.imports())
+ && safeSubtreeListMatch(node.types(), o.types()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ConditionalExpression node, Object other) {
+ if (!(other instanceof ConditionalExpression)) {
+ return false;
+ }
+ ConditionalExpression o = (ConditionalExpression) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getThenExpression(), o.getThenExpression())
+ && safeSubtreeMatch(node.getElseExpression(), o.getElseExpression()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ConstructorInvocation node, Object other) {
+ if (!(other instanceof ConstructorInvocation)) {
+ return false;
+ }
+ ConstructorInvocation o = (ConstructorInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return safeSubtreeListMatch(node.arguments(), o.arguments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ContinueStatement node, Object other) {
+ if (!(other instanceof ContinueStatement)) {
+ return false;
+ }
+ ContinueStatement o = (ContinueStatement) other;
+ return safeSubtreeMatch(node.getLabel(), o.getLabel());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(DoStatement node, Object other) {
+ if (!(other instanceof DoStatement)) {
+ return false;
+ }
+ DoStatement o = (DoStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(EmptyStatement node, Object other) {
+ if (!(other instanceof EmptyStatement)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(EnhancedForStatement node, Object other) {
+ if (!(other instanceof EnhancedForStatement)) {
+ return false;
+ }
+ EnhancedForStatement o = (EnhancedForStatement) other;
+ return (
+ safeSubtreeMatch(node.getParameter(), o.getParameter())
+ && safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ExpressionStatement node, Object other) {
+ if (!(other instanceof ExpressionStatement)) {
+ return false;
+ }
+ ExpressionStatement o = (ExpressionStatement) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(FieldAccess node, Object other) {
+ if (!(other instanceof FieldAccess)) {
+ return false;
+ }
+ FieldAccess o = (FieldAccess) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(FieldDeclaration node, Object other) {
+ if (!(other instanceof FieldDeclaration)) {
+ return false;
+ }
+ FieldDeclaration o = (FieldDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.fragments(), o.fragments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ForStatement node, Object other) {
+ if (!(other instanceof ForStatement)) {
+ return false;
+ }
+ ForStatement o = (ForStatement) other;
+ return (
+ safeSubtreeListMatch(node.initializers(), o.initializers())
+ && safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.updaters(), o.updaters())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ public boolean match(ForInStatement node, Object other) {
+ if (!(other instanceof ForInStatement)) {
+ return false;
+ }
+ ForInStatement o = (ForInStatement) other;
+ return (
+ safeSubtreeMatch(node.getIterationVariable(), o.getIterationVariable())
+ && safeSubtreeMatch(node.getCollection(), o.getCollection())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(IfStatement node, Object other) {
+ if (!(other instanceof IfStatement)) {
+ return false;
+ }
+ IfStatement o = (IfStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getThenStatement(), o.getThenStatement())
+ && safeSubtreeMatch(node.getElseStatement(), o.getElseStatement()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ImportDeclaration node, Object other) {
+ if (!(other instanceof ImportDeclaration)) {
+ return false;
+ }
+ ImportDeclaration o = (ImportDeclaration) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (node.isStatic() != o.isStatic()) {
+ return false;
+ }
+ }
+ if (node.isFileImport() != o.isFileImport()) {
+ return false;
+ }
+ return (
+ safeSubtreeMatch(node.getName(), o.getName())
+ && node.isOnDemand() == o.isOnDemand());
+ }
+
+
+ public boolean match(InferredType node, Object other) {
+ if (!(other instanceof InferredType)) {
+ return false;
+ }
+ InferredType o = (InferredType) other;
+ if (node.type==null || o.type==null)
+ return true;
+
+ return node.type.equals(o.type);
+ }
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(InfixExpression node, Object other) {
+ if (!(other instanceof InfixExpression)) {
+ return false;
+ }
+ InfixExpression o = (InfixExpression) other;
+ // be careful not to trigger lazy creation of extended operand lists
+ if (node.hasExtendedOperands() && o.hasExtendedOperands()) {
+ if (!safeSubtreeListMatch(node.extendedOperands(), o.extendedOperands())) {
+ return false;
+ }
+ }
+ if (node.hasExtendedOperands() != o.hasExtendedOperands()) {
+ return false;
+ }
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand())
+ && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(InstanceofExpression node, Object other) {
+ if (!(other instanceof InstanceofExpression)) {
+ return false;
+ }
+ InstanceofExpression o = (InstanceofExpression) other;
+ return (
+ safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand())
+ && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(Initializer node, Object other) {
+ if (!(other instanceof Initializer)) {
+ return false;
+ }
+ Initializer o = (Initializer) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * Unlike other node types, the behavior of the default
+ * implementation is controlled by a constructor-supplied
+ * parameter {@link #ASTMatcher(boolean) ASTMatcher(boolean)}
+ * which is false
if not specified.
+ * When this parameter is true
, the implementation
+ * tests whether the other object is also a Javadoc
+ * with structurally isomorphic child subtrees; the comment string
+ * (Javadoc.getComment()
) is ignored.
+ * Conversely, when the parameter is false
, the
+ * implementation tests whether the other object is also a
+ * Javadoc
with exactly the same comment string;
+ * the tag elements ({@link JSdoc#tags() Javadoc.tags} are
+ * ignored. Subclasses may reimplement.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ * @see #ASTMatcher()
+ * @see #ASTMatcher(boolean)
+ */
+ public boolean match(JSdoc node, Object other) {
+ if (!(other instanceof JSdoc)) {
+ return false;
+ }
+ JSdoc o = (JSdoc) other;
+ if (this.matchDocTags) {
+ return safeSubtreeListMatch(node.tags(), o.tags());
+ } else {
+ return compareDeprecatedComment(node, o);
+ }
+ }
+
+ /**
+ * Return whether the deprecated comment strings of the given jsdoc are equals.
+ *
+ * Note the only purpose of this method is to hide deprecated warnings.
+ * @deprecated mark deprecated to hide deprecated usage
+ */
+ private boolean compareDeprecatedComment(JSdoc first, JSdoc second) {
+ if (first.getAST().apiLevel == AST.JLS2_INTERNAL) {
+ return safeEquals(first.getComment(), second.getComment());
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(LabeledStatement node, Object other) {
+ if (!(other instanceof LabeledStatement)) {
+ return false;
+ }
+ LabeledStatement o = (LabeledStatement) other;
+ return (
+ safeSubtreeMatch(node.getLabel(), o.getLabel())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type. Subclasses may override
+ * this method as needed.
+ *
+ * Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(LineComment node, Object other) {
+ if (!(other instanceof LineComment)) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean match(ListExpression node, Object other) {
+ if (!(other instanceof ListExpression)) {
+ return false;
+ }
+ ListExpression o = (ListExpression) other;
+ return safeSubtreeListMatch(node.expressions(), o.expressions());
+ }
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(MemberRef node, Object other) {
+ if (!(other instanceof MemberRef)) {
+ return false;
+ }
+ MemberRef o = (MemberRef) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(FunctionRef node, Object other) {
+ if (!(other instanceof FunctionRef)) {
+ return false;
+ }
+ FunctionRef o = (FunctionRef) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.parameters(), o.parameters()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(FunctionRefParameter node, Object other) {
+ if (!(other instanceof FunctionRefParameter)) {
+ return false;
+ }
+ FunctionRefParameter o = (FunctionRefParameter) other;
+ int level = node.getAST().apiLevel;
+ if (level >= AST.JLS3) {
+ if (node.isVarargs() != o.isVarargs()) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * Note that extra array dimensions are compared since they are an
+ * important part of the method declaration.
+ *
+ *
+ * Note that the method return types are compared even for constructor
+ * declarations.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(FunctionDeclaration node, Object other) {
+ if (!(other instanceof FunctionDeclaration)) {
+ return false;
+ }
+ FunctionDeclaration o = (FunctionDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.internalGetReturnType(), o.internalGetReturnType())) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getReturnType2(), o.getReturnType2())) {
+ return false;
+ }
+ }
+ return ((node.isConstructor() == o.isConstructor())
+ && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ // n.b. compare return type even for constructors
+ && safeSubtreeListMatch(node.parameters(), o.parameters())
+ && node.getExtraDimensions() == o.getExtraDimensions()
+ && safeSubtreeListMatch(node.thrownExceptions(), o.thrownExceptions())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(FunctionInvocation node, Object other) {
+ if (!(other instanceof FunctionInvocation)) {
+ return false;
+ }
+ FunctionInvocation o = (FunctionInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.arguments(), o.arguments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(Modifier node, Object other) {
+ if (!(other instanceof Modifier)) {
+ return false;
+ }
+ Modifier o = (Modifier) other;
+ return (node.getKeyword() == o.getKeyword());
+ }
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(NullLiteral node, Object other) {
+ if (!(other instanceof NullLiteral)) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean match(UndefinedLiteral node, Object other) {
+ if (!(other instanceof UndefinedLiteral)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(NumberLiteral node, Object other) {
+ if (!(other instanceof NumberLiteral)) {
+ return false;
+ }
+ NumberLiteral o = (NumberLiteral) other;
+ return safeEquals(node.getToken(), o.getToken());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(PackageDeclaration node, Object other) {
+ if (!(other instanceof PackageDeclaration)) {
+ return false;
+ }
+ PackageDeclaration o = (PackageDeclaration) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())) {
+ return false;
+ }
+ if (!safeSubtreeListMatch(node.annotations(), o.annotations())) {
+ return false;
+ }
+ }
+ return safeSubtreeMatch(node.getName(), o.getName());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ParenthesizedExpression node, Object other) {
+ if (!(other instanceof ParenthesizedExpression)) {
+ return false;
+ }
+ ParenthesizedExpression o = (ParenthesizedExpression) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(PostfixExpression node, Object other) {
+ if (!(other instanceof PostfixExpression)) {
+ return false;
+ }
+ PostfixExpression o = (PostfixExpression) other;
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getOperand(), o.getOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(PrefixExpression node, Object other) {
+ if (!(other instanceof PrefixExpression)) {
+ return false;
+ }
+ PrefixExpression o = (PrefixExpression) other;
+ return (
+ node.getOperator().equals(o.getOperator())
+ && safeSubtreeMatch(node.getOperand(), o.getOperand()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(PrimitiveType node, Object other) {
+ if (!(other instanceof PrimitiveType)) {
+ return false;
+ }
+ PrimitiveType o = (PrimitiveType) other;
+ return (node.getPrimitiveTypeCode() == o.getPrimitiveTypeCode());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(QualifiedName node, Object other) {
+ if (!(other instanceof QualifiedName)) {
+ return false;
+ }
+ QualifiedName o = (QualifiedName) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(QualifiedType node, Object other) {
+ if (!(other instanceof QualifiedType)) {
+ return false;
+ }
+ QualifiedType o = (QualifiedType) other;
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ReturnStatement node, Object other) {
+ if (!(other instanceof ReturnStatement)) {
+ return false;
+ }
+ ReturnStatement o = (ReturnStatement) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SimpleName node, Object other) {
+ if (!(other instanceof SimpleName)) {
+ return false;
+ }
+ SimpleName o = (SimpleName) other;
+ return node.getIdentifier().equals(o.getIdentifier());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SimpleType node, Object other) {
+ if (!(other instanceof SimpleType)) {
+ return false;
+ }
+ SimpleType o = (SimpleType) other;
+ return safeSubtreeMatch(node.getName(), o.getName());
+ }
+
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * Note that extra array dimensions and the variable arity flag
+ * are compared since they are both important parts of the declaration.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SingleVariableDeclaration node, Object other) {
+ if (!(other instanceof SingleVariableDeclaration)) {
+ return false;
+ }
+ SingleVariableDeclaration o = (SingleVariableDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ if (node.isVarargs() != o.isVarargs()) {
+ return false;
+ }
+ }
+ return
+ safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && node.getExtraDimensions() == o.getExtraDimensions()
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(StringLiteral node, Object other) {
+ if (!(other instanceof StringLiteral)) {
+ return false;
+ }
+ StringLiteral o = (StringLiteral) other;
+ return safeEquals(node.getEscapedValue(), o.getEscapedValue());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SuperConstructorInvocation node, Object other) {
+ if (!(other instanceof SuperConstructorInvocation)) {
+ return false;
+ }
+ SuperConstructorInvocation o = (SuperConstructorInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.arguments(), o.arguments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SuperFieldAccess node, Object other) {
+ if (!(other instanceof SuperFieldAccess)) {
+ return false;
+ }
+ SuperFieldAccess o = (SuperFieldAccess) other;
+ return (
+ safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeMatch(node.getQualifier(), o.getQualifier()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SuperMethodInvocation node, Object other) {
+ if (!(other instanceof SuperMethodInvocation)) {
+ return false;
+ }
+ SuperMethodInvocation o = (SuperMethodInvocation) other;
+ if (node.getAST().apiLevel >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.arguments(), o.arguments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SwitchCase node, Object other) {
+ if (!(other instanceof SwitchCase)) {
+ return false;
+ }
+ SwitchCase o = (SwitchCase) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(SwitchStatement node, Object other) {
+ if (!(other instanceof SwitchStatement)) {
+ return false;
+ }
+ SwitchStatement o = (SwitchStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeListMatch(node.statements(), o.statements()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(TagElement node, Object other) {
+ if (!(other instanceof TagElement)) {
+ return false;
+ }
+ TagElement o = (TagElement) other;
+ return (
+ safeEquals(node.getTagName(), o.getTagName())
+ && safeSubtreeListMatch(node.fragments(), o.fragments()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(TextElement node, Object other) {
+ if (!(other instanceof TextElement)) {
+ return false;
+ }
+ TextElement o = (TextElement) other;
+ return safeEquals(node.getText(), o.getText());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ThisExpression node, Object other) {
+ if (!(other instanceof ThisExpression)) {
+ return false;
+ }
+ ThisExpression o = (ThisExpression) other;
+ return safeSubtreeMatch(node.getQualifier(), o.getQualifier());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(ThrowStatement node, Object other) {
+ if (!(other instanceof ThrowStatement)) {
+ return false;
+ }
+ ThrowStatement o = (ThrowStatement) other;
+ return safeSubtreeMatch(node.getExpression(), o.getExpression());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(TryStatement node, Object other) {
+ if (!(other instanceof TryStatement)) {
+ return false;
+ }
+ TryStatement o = (TryStatement) other;
+ return (
+ safeSubtreeMatch(node.getBody(), o.getBody())
+ && safeSubtreeListMatch(node.catchClauses(), o.catchClauses())
+ && safeSubtreeMatch(node.getFinally(), o.getFinally()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(TypeDeclaration node, Object other) {
+ if (!(other instanceof TypeDeclaration)) {
+ return false;
+ }
+ TypeDeclaration o = (TypeDeclaration) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.internalGetSuperclass(), o.internalGetSuperclass())) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ if (!safeSubtreeMatch(node.getSuperclassType(), o.getSuperclassType())) {
+ return false;
+ }
+ }
+ return (
+ safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+ && safeSubtreeMatch(node.getName(), o.getName())
+ && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()));
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(TypeDeclarationStatement node, Object other) {
+ if (!(other instanceof TypeDeclarationStatement)) {
+ return false;
+ }
+ TypeDeclarationStatement o = (TypeDeclarationStatement) other;
+ return safeSubtreeMatch(node.getDeclaration(), o.getDeclaration());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(TypeLiteral node, Object other) {
+ if (!(other instanceof TypeLiteral)) {
+ return false;
+ }
+ TypeLiteral o = (TypeLiteral) other;
+ return safeSubtreeMatch(node.getType(), o.getType());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(VariableDeclarationExpression node, Object other) {
+ if (!(other instanceof VariableDeclarationExpression)) {
+ return false;
+ }
+ VariableDeclarationExpression o = (VariableDeclarationExpression) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.fragments(), o.fragments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * Note that extra array dimensions are compared since they are an
+ * important part of the type of the variable.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(VariableDeclarationFragment node, Object other) {
+ if (!(other instanceof VariableDeclarationFragment)) {
+ return false;
+ }
+ VariableDeclarationFragment o = (VariableDeclarationFragment) other;
+ return safeSubtreeMatch(node.getName(), o.getName())
+ && node.getExtraDimensions() == o.getExtraDimensions()
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(VariableDeclarationStatement node, Object other) {
+ if (!(other instanceof VariableDeclarationStatement)) {
+ return false;
+ }
+ VariableDeclarationStatement o = (VariableDeclarationStatement) other;
+ int level = node.getAST().apiLevel;
+ if (level == AST.JLS2_INTERNAL) {
+ if (node.getModifiers() != o.getModifiers()) {
+ return false;
+ }
+ }
+ if (level >= AST.JLS3) {
+ if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+ return false;
+ }
+ }
+ return safeSubtreeMatch(node.getType(), o.getType())
+ && safeSubtreeListMatch(node.fragments(), o.fragments());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ *
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ *
+ *
+ * @param node the node
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match or the other object has a
+ * different node type or is null
+ */
+ public boolean match(WhileStatement node, Object other) {
+ if (!(other instanceof WhileStatement)) {
+ return false;
+ }
+ WhileStatement o = (WhileStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ public boolean match(WithStatement node, Object other) {
+ if (!(other instanceof WithStatement)) {
+ return false;
+ }
+ WithStatement o = (WithStatement) other;
+ return (
+ safeSubtreeMatch(node.getExpression(), o.getExpression())
+ && safeSubtreeMatch(node.getBody(), o.getBody()));
+ }
+
+ public boolean match(ObjectLiteral node, Object other) {
+ if (!(other instanceof ObjectLiteral)) {
+ return false;
+ }
+ ObjectLiteral o = (ObjectLiteral) other;
+ return safeSubtreeListMatch(node.fields(), o.fields());
+ }
+
+ public boolean match(ObjectLiteralField node, Object other) {
+ if (!(other instanceof ObjectLiteralField)) {
+ return false;
+ }
+ ObjectLiteralField o = (ObjectLiteralField) other;
+ return safeSubtreeMatch(node.getFieldName(), o.getFieldName())
+ && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTNode.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTNode.java
new file mode 100644
index 0000000..2c7b0b1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTNode.java
@@ -0,0 +1,2635 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * bug 227489 - Etienne Pfister
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstract superclass of all Abstract Syntax Tree (AST) node types.
+ *
+ * An AST node represents a JavaScript source code construct, such
+ * as a name, type, expression, statement, or declaration.
+ *
+ *
+ * Each AST node belongs to a unique AST instance, called the owning AST.
+ * The children of an AST node always have the same owner as their parent node.
+ * If a node from one AST is to be added to a different AST, the subtree must
+ * be cloned first to ensure that the added nodes have the correct owning AST.
+ *
+ *
+ * When an AST node is part of an AST, it has a unique parent node.
+ * Clients can navigate upwards, from child to parent, as well as downwards,
+ * from parent to child. Newly created nodes are unparented. When an
+ * unparented node is set as a child of a node (using a
+ * setCHILD
method), its parent link is set automatically
+ * and the parent link of the former child is set to null
.
+ * For nodes with properties that include a list of children (for example,
+ * Block
whose statements
property is a list
+ * of statements), adding or removing an element to/for the list property
+ * automatically updates the parent links. These lists support the
+ * List.set
method; however, the constraint that the same
+ * node cannot appear more than once means that this method cannot be used
+ * to swap elements without first removing the node.
+ *
+ *
+ * ASTs must not contain cycles. All operations that could create a cycle
+ * detect this possibility and fail.
+ *
+ *
+ * ASTs do not contain "holes" (missing subtrees). If a node is required to
+ * have a certain property, a syntactically plausible initial value is
+ * always supplied.
+ *
+ *
+ * The hierarchy of AST node types has some convenient groupings marked
+ * by abstract superclasses:
+ *
+ * - expressions -
Expression
+ * - names -
Name
(a sub-kind of expression)
+ * - statements -
Statement
+ * - types -
Type
+ * - type body declarations -
BodyDeclaration
+ *
+ *
+ *
+ * Abstract syntax trees may be hand constructed by clients, using the
+ * newTYPE
factory methods (see AST
) to
+ * create new nodes, and the various setCHILD
methods
+ * to connect them together.
+ *
+ *
+ * The class {@link ASTParser} parses a string
+ * containing a JavaScript source code and returns an abstract syntax tree
+ * for it. The resulting nodes carry source ranges relating the node back to
+ * the original source characters. The source range covers the construct
+ * as a whole.
+ *
+ *
+ * Each AST node carries bit flags, which may convey additional information about
+ * the node. For instance, the parser uses a flag to indicate a syntax error.
+ * Newly created nodes have no flags set.
+ *
+ *
+ * Each AST node is capable of carrying an open-ended collection of
+ * client-defined properties. Newly created nodes have none.
+ * getProperty
and setProperty
are used to access
+ * these properties.
+ *
+ *
+ * AST nodes are thread-safe for readers provided there are no active writers.
+ * If one thread is modifying an AST, including creating new nodes or cloning
+ * existing ones, it is not safe for another thread to read, visit,
+ * write, create, or clone any of the nodes on the same AST.
+ * When synchronization is required, consider using the common AST
+ * object that owns the node; that is, use
+ * synchronize (node.getAST()) {...}
.
+ *
+ *
+ * ASTs also support the visitor pattern; see the class ASTVisitor
+ * for details.
+ *
+ *
+ * JavaScript units created by ASTParser
from a
+ * source document can be serialized after arbitrary modifications
+ * with minimal loss of original formatting. See
+ * {@link JavaScriptUnit#recordModifications()} for details.
+ * See also {@link org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite} for
+ * an alternative way to describe and serialize changes to a
+ * read-only AST.
+ *
+ * This class is not intended to be subclassed by clients.
+ *
+ * @see ASTParser
+ * @see ASTVisitor
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class ASTNode {
+ /*
+ * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
+ *
+ * There are several things that need to be changed when a
+ * new concrete AST node type (call it "FooBar"):
+ *
+ * 1. Create the FooBar AST node type class.
+ * The most effective way to do this is to copy a similar
+ * existing concrete node class to get a template that
+ * includes all the framework methods that must be implemented.
+ *
+ * 2. Add node type constant ASTNode.FOO_BAR.
+ * Node constants are numbered consecutively. Add the
+ * constant after the existing ones.
+ *
+ * 3. Add entry to ASTNode.nodeClassForType(int).
+ *
+ * 4. Add AST.newFooBar() factory method.
+ *
+ * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
+ *
+ * 6. Add ASTMatcher.match(FooBar,Object) method.
+ *
+ * 7. Ensure that SimpleName.isDeclaration() covers FooBar
+ * nodes if required.
+ *
+ * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
+ * how these nodes should be serialized.
+ *
+ * 9. Update the AST test suites.
+ *
+ * The next steps are to update AST.parse* to start generating
+ * the new type of nodes, and ASTRewrite to serialize them back out.
+ */
+
+ /**
+ * Node type constant indicating a node of type
+ * AnonymousClassDeclaration
.
+ * @see AnonymousClassDeclaration
+ */
+ public static final int ANONYMOUS_CLASS_DECLARATION = 1;
+
+ /**
+ * Node type constant indicating a node of type
+ * ArrayAccess
.
+ * @see ArrayAccess
+ */
+ public static final int ARRAY_ACCESS = 2;
+
+ /**
+ * Node type constant indicating a node of type
+ * ArrayCreation
.
+ * @see ArrayCreation
+ */
+ public static final int ARRAY_CREATION = 3;
+
+ /**
+ * Node type constant indicating a node of type
+ * ArrayInitializer
.
+ * @see ArrayInitializer
+ */
+ public static final int ARRAY_INITIALIZER = 4;
+
+ /**
+ * Node type constant indicating a node of type
+ * ArrayType
.
+ * @see ArrayType
+ */
+ public static final int ARRAY_TYPE = 5;
+
+ /**
+ * Node type constant indicating a node of type
+ * Assignment
.
+ * @see Assignment
+ */
+ public static final int ASSIGNMENT = 7;
+
+ /**
+ * Node type constant indicating a node of type
+ * Block
.
+ * @see Block
+ */
+ public static final int BLOCK = 8;
+
+ /**
+ * Node type constant indicating a node of type
+ * BooleanLiteral
.
+ * @see BooleanLiteral
+ */
+ public static final int BOOLEAN_LITERAL = 9;
+
+ /**
+ * Node type constant indicating a node of type
+ * BreakStatement
.
+ * @see BreakStatement
+ */
+ public static final int BREAK_STATEMENT = 10;
+
+ /**
+ * Node type constant indicating a node of type
+ * CatchClause
.
+ * @see CatchClause
+ */
+ public static final int CATCH_CLAUSE = 12;
+
+ /**
+ * Node type constant indicating a node of type
+ * CharacterLiteral
.
+ * @see CharacterLiteral
+ */
+ public static final int CHARACTER_LITERAL = 13;
+
+ /**
+ * Node type constant indicating a node of type
+ * ClassInstanceCreation
.
+ * @see ClassInstanceCreation
+ */
+ public static final int CLASS_INSTANCE_CREATION = 14;
+
+ /**
+ * Node type constant indicating a node of type
+ * JavaScriptUnit
.
+ * @see JavaScriptUnit
+ */
+ public static final int JAVASCRIPT_UNIT = 15;
+
+ /**
+ * Node type constant indicating a node of type
+ * ConditionalExpression
.
+ * @see ConditionalExpression
+ */
+ public static final int CONDITIONAL_EXPRESSION = 16;
+
+ /**
+ * Node type constant indicating a node of type
+ * ConstructorInvocation
.
+ * @see ConstructorInvocation
+ */
+ public static final int CONSTRUCTOR_INVOCATION = 17;
+
+ /**
+ * Node type constant indicating a node of type
+ * ContinueStatement
.
+ * @see ContinueStatement
+ */
+ public static final int CONTINUE_STATEMENT = 18;
+
+ /**
+ * Node type constant indicating a node of type
+ * DoStatement
.
+ * @see DoStatement
+ */
+ public static final int DO_STATEMENT = 19;
+
+ /**
+ * Node type constant indicating a node of type
+ * EmptyStatement
.
+ * @see EmptyStatement
+ */
+ public static final int EMPTY_STATEMENT = 20;
+
+ /**
+ * Node type constant indicating a node of type
+ * ExpressionStatement
.
+ * @see ExpressionStatement
+ */
+ public static final int EXPRESSION_STATEMENT = 21;
+
+ /**
+ * Node type constant indicating a node of type
+ * FieldAccess
.
+ * @see FieldAccess
+ */
+ public static final int FIELD_ACCESS = 22;
+
+ /**
+ * Node type constant indicating a node of type
+ * FieldDeclaration
.
+ * @see FieldDeclaration
+ */
+ public static final int FIELD_DECLARATION = 23;
+
+ /**
+ * Node type constant indicating a node of type
+ * ForStatement
.
+ * @see ForStatement
+ */
+ public static final int FOR_STATEMENT = 24;
+
+ /**
+ * Node type constant indicating a node of type
+ * IfStatement
.
+ * @see IfStatement
+ */
+ public static final int IF_STATEMENT = 25;
+
+ /**
+ * Node type constant indicating a node of type
+ * ImportDeclaration
.
+ * @see ImportDeclaration
+ */
+ public static final int IMPORT_DECLARATION = 26;
+
+ /**
+ * Node type constant indicating a node of type
+ * InfixExpression
.
+ * @see InfixExpression
+ */
+ public static final int INFIX_EXPRESSION = 27;
+
+ /**
+ * Node type constant indicating a node of type
+ * Initializer
.
+ * @see Initializer
+ */
+ public static final int INITIALIZER = 28;
+
+ /**
+ * Node type constant indicating a node of type
+ * Javadoc
.
+ * @see JSdoc
+ */
+ public static final int JSDOC = 29;
+
+ /**
+ * Node type constant indicating a node of type
+ * LabeledStatement
.
+ * @see LabeledStatement
+ */
+ public static final int LABELED_STATEMENT = 30;
+
+ /**
+ * Node type constant indicating a node of type
+ * FunctionDeclaration
.
+ * @see FunctionDeclaration
+ */
+ public static final int FUNCTION_DECLARATION = 31;
+
+ /**
+ * Node type constant indicating a node of type
+ * FunctionInvocation
.
+ * @see FunctionInvocation
+ */
+ public static final int FUNCTION_INVOCATION = 32;
+
+ /**
+ * Node type constant indicating a node of type
+ * NullLiteral
.
+ * @see NullLiteral
+ */
+ public static final int NULL_LITERAL = 33;
+
+ /**
+ * Node type constant indicating a node of type
+ * NumberLiteral
.
+ * @see NumberLiteral
+ */
+ public static final int NUMBER_LITERAL = 34;
+
+ /**
+ * Node type constant indicating a node of type
+ * PackageDeclaration
.
+ * @see PackageDeclaration
+ */
+ public static final int PACKAGE_DECLARATION = 35;
+
+ /**
+ * Node type constant indicating a node of type
+ * ParenthesizedExpression
.
+ * @see ParenthesizedExpression
+ */
+ public static final int PARENTHESIZED_EXPRESSION = 36;
+
+ /**
+ * Node type constant indicating a node of type
+ * PostfixExpression
.
+ * @see PostfixExpression
+ */
+ public static final int POSTFIX_EXPRESSION = 37;
+
+ /**
+ * Node type constant indicating a node of type
+ * PrefixExpression
.
+ * @see PrefixExpression
+ */
+ public static final int PREFIX_EXPRESSION = 38;
+
+ /**
+ * Node type constant indicating a node of type
+ * PrimitiveType
.
+ * @see PrimitiveType
+ */
+ public static final int PRIMITIVE_TYPE = 39;
+
+ /**
+ * Node type constant indicating a node of type
+ * QualifiedName
.
+ * @see QualifiedName
+ */
+ public static final int QUALIFIED_NAME = 40;
+
+ /**
+ * Node type constant indicating a node of type
+ * ReturnStatement
.
+ * @see ReturnStatement
+ */
+ public static final int RETURN_STATEMENT = 41;
+
+ /**
+ * Node type constant indicating a node of type
+ * SimpleName
.
+ * @see SimpleName
+ */
+ public static final int SIMPLE_NAME = 42;
+
+ /**
+ * Node type constant indicating a node of type
+ * SimpleType
.
+ * @see SimpleType
+ */
+ public static final int SIMPLE_TYPE = 43;
+
+ /**
+ * Node type constant indicating a node of type
+ * SingleVariableDeclaration
.
+ * @see SingleVariableDeclaration
+ */
+ public static final int SINGLE_VARIABLE_DECLARATION = 44;
+
+ /**
+ * Node type constant indicating a node of type
+ * StringLiteral
.
+ * @see StringLiteral
+ */
+ public static final int STRING_LITERAL = 45;
+
+ /**
+ * Node type constant indicating a node of type
+ * SuperConstructorInvocation
.
+ * @see SuperConstructorInvocation
+ */
+ public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
+
+ /**
+ * Node type constant indicating a node of type
+ * SuperFieldAccess
.
+ * @see SuperFieldAccess
+ */
+ public static final int SUPER_FIELD_ACCESS = 47;
+
+ /**
+ * Node type constant indicating a node of type
+ * SuperMethodInvocation
.
+ * @see SuperMethodInvocation
+ */
+ public static final int SUPER_METHOD_INVOCATION = 48;
+
+ /**
+ * Node type constant indicating a node of type
+ * SwitchCase
.
+ * @see SwitchCase
+ */
+ public static final int SWITCH_CASE = 49;
+
+ /**
+ * Node type constant indicating a node of type
+ * SwitchStatement
.
+ * @see SwitchStatement
+ */
+ public static final int SWITCH_STATEMENT = 50;
+
+ /**
+ * Node type constant indicating a node of type
+ * ThisExpression
.
+ * @see ThisExpression
+ */
+ public static final int THIS_EXPRESSION = 52;
+
+ /**
+ * Node type constant indicating a node of type
+ * ThrowStatement
.
+ * @see ThrowStatement
+ */
+ public static final int THROW_STATEMENT = 53;
+
+ /**
+ * Node type constant indicating a node of type
+ * TryStatement
.
+ * @see TryStatement
+ */
+ public static final int TRY_STATEMENT = 54;
+
+ /**
+ * Node type constant indicating a node of type
+ * TypeDeclaration
.
+ * @see TypeDeclaration
+ */
+ public static final int TYPE_DECLARATION = 55;
+
+ /**
+ * Node type constant indicating a node of type
+ * TypeDeclarationStatement
.
+ * @see TypeDeclarationStatement
+ */
+ public static final int TYPE_DECLARATION_STATEMENT = 56;
+
+ /**
+ * Node type constant indicating a node of type
+ * TypeLiteral
.
+ * @see TypeLiteral
+ */
+ public static final int TYPE_LITERAL = 57;
+
+ /**
+ * Node type constant indicating a node of type
+ * VariableDeclarationExpression
.
+ * @see VariableDeclarationExpression
+ */
+ public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
+
+ /**
+ * Node type constant indicating a node of type
+ * VariableDeclarationFragment
.
+ * @see VariableDeclarationFragment
+ */
+ public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
+
+ /**
+ * Node type constant indicating a node of type
+ * VariableDeclarationStatement
.
+ * @see VariableDeclarationStatement
+ */
+ public static final int VARIABLE_DECLARATION_STATEMENT = 60;
+
+ /**
+ * Node type constant indicating a node of type
+ * WhileStatement
.
+ * @see WhileStatement
+ */
+ public static final int WHILE_STATEMENT = 61;
+
+ /**
+ * Node type constant indicating a node of type
+ * InstanceofExpression
.
+ * @see InstanceofExpression
+ */
+ public static final int INSTANCEOF_EXPRESSION = 62;
+
+ /**
+ * Node type constant indicating a node of type
+ * LineComment
.
+ * @see LineComment
+ */
+ public static final int LINE_COMMENT = 63;
+
+ /**
+ * Node type constant indicating a node of type
+ * BlockComment
.
+ * @see BlockComment
+ *
+ */
+ public static final int BLOCK_COMMENT = 64;
+
+ /**
+ * Node type constant indicating a node of type
+ * TagElement
.
+ * @see TagElement
+ *
+ */
+ public static final int TAG_ELEMENT = 65;
+
+ /**
+ * Node type constant indicating a node of type
+ * TextElement
.
+ * @see TextElement
+ *
+ */
+ public static final int TEXT_ELEMENT = 66;
+
+ /**
+ * Node type constant indicating a node of type
+ * MemberRef
.
+ * @see MemberRef
+ *
+ */
+ public static final int MEMBER_REF = 67;
+
+ /**
+ * Node type constant indicating a node of type
+ * FunctionRef
.
+ * @see FunctionRef
+ *
+ */
+ public static final int FUNCTION_REF = 68;
+
+ /**
+ * Node type constant indicating a node of type
+ * FunctionRefParameter
.
+ * @see FunctionRefParameter
+ *
+ */
+ public static final int FUNCTION_REF_PARAMETER = 69;
+
+ /**
+ * Node type constant indicating a node of type
+ * EnhancedForStatement
.
+ * @see EnhancedForStatement
+ *
+ */
+ public static final int ENHANCED_FOR_STATEMENT = 70;
+
+ /**
+ * Node type constant indicating a node of type
+ * QualifiedType
.
+ * @see QualifiedType
+ *
+ */
+ public static final int QUALIFIED_TYPE = 75;
+
+
+ public static final int FOR_IN_STATEMENT = 83;
+ public static final int FUNCTION_EXPRESSION = 84;
+ public static final int OBJECT_LITERAL = 85;
+ public static final int OBJECT_LITERAL_FIELD = 86;
+ public static final int UNDEFINED_LITERAL = 87;
+ public static final int REGULAR_EXPRESSION_LITERAL = 88;
+ public static final int INFERRED_TYPE = 89;
+ public static final int WITH_STATEMENT = 90;
+ public static final int LIST_EXPRESSION = 91;
+ public static final int EMPTY_EXPRESSION = 92;
+
+
+
+
+
+ /**
+ * Node type constant indicating a node of type
+ * Modifier
.
+ * @see Modifier
+ */
+ public static final int MODIFIER = 100;
+
+ /**
+ * Returns the node class for the corresponding node type.
+ *
+ * @param nodeType AST node type
+ * @return the corresponding ASTNode
subclass
+ * @exception IllegalArgumentException if nodeType
is
+ * not a legal AST node type
+ * @see #getNodeType()
+ */
+ public static Class nodeClassForType(int nodeType) {
+ switch (nodeType) {
+ case ANONYMOUS_CLASS_DECLARATION :
+ return AnonymousClassDeclaration.class;
+ case ARRAY_ACCESS :
+ return ArrayAccess.class;
+ case ARRAY_CREATION :
+ return ArrayCreation.class;
+ case ARRAY_INITIALIZER :
+ return ArrayInitializer.class;
+ case ARRAY_TYPE :
+ return ArrayType.class;
+ case ASSIGNMENT :
+ return Assignment.class;
+ case BLOCK :
+ return Block.class;
+ case BLOCK_COMMENT :
+ return BlockComment.class;
+ case BOOLEAN_LITERAL :
+ return BooleanLiteral.class;
+ case BREAK_STATEMENT :
+ return BreakStatement.class;
+ case CATCH_CLAUSE :
+ return CatchClause.class;
+ case CHARACTER_LITERAL :
+ return CharacterLiteral.class;
+ case CLASS_INSTANCE_CREATION :
+ return ClassInstanceCreation.class;
+ case JAVASCRIPT_UNIT :
+ return JavaScriptUnit.class;
+ case CONDITIONAL_EXPRESSION :
+ return ConditionalExpression.class;
+ case CONSTRUCTOR_INVOCATION :
+ return ConstructorInvocation.class;
+ case CONTINUE_STATEMENT :
+ return ContinueStatement.class;
+ case DO_STATEMENT :
+ return DoStatement.class;
+ case EMPTY_STATEMENT :
+ return EmptyStatement.class;
+ case ENHANCED_FOR_STATEMENT :
+ return EnhancedForStatement.class;
+ case EXPRESSION_STATEMENT :
+ return ExpressionStatement.class;
+ case FIELD_ACCESS :
+ return FieldAccess.class;
+ case FIELD_DECLARATION :
+ return FieldDeclaration.class;
+ case FOR_STATEMENT :
+ return ForStatement.class;
+ case FOR_IN_STATEMENT:
+ return ForInStatement.class;
+ case IF_STATEMENT :
+ return IfStatement.class;
+ case IMPORT_DECLARATION :
+ return ImportDeclaration.class;
+ case INFIX_EXPRESSION :
+ return InfixExpression.class;
+ case INITIALIZER :
+ return Initializer.class;
+ case INSTANCEOF_EXPRESSION :
+ return InstanceofExpression.class;
+ case JSDOC :
+ return JSdoc.class;
+ case LABELED_STATEMENT :
+ return LabeledStatement.class;
+ case LINE_COMMENT :
+ return LineComment.class;
+ case MEMBER_REF :
+ return MemberRef.class;
+ case FUNCTION_DECLARATION :
+ return FunctionDeclaration.class;
+ case FUNCTION_INVOCATION :
+ return FunctionInvocation.class;
+ case FUNCTION_REF :
+ return FunctionRef.class;
+ case FUNCTION_REF_PARAMETER :
+ return FunctionRefParameter.class;
+ case MODIFIER :
+ return Modifier.class;
+ case NULL_LITERAL :
+ return NullLiteral.class;
+ case UNDEFINED_LITERAL :
+ return UndefinedLiteral.class;
+ case NUMBER_LITERAL :
+ return NumberLiteral.class;
+ case PACKAGE_DECLARATION :
+ return PackageDeclaration.class;
+ case PARENTHESIZED_EXPRESSION :
+ return ParenthesizedExpression.class;
+ case POSTFIX_EXPRESSION :
+ return PostfixExpression.class;
+ case PREFIX_EXPRESSION :
+ return PrefixExpression.class;
+ case PRIMITIVE_TYPE :
+ return PrimitiveType.class;
+ case QUALIFIED_NAME :
+ return QualifiedName.class;
+ case QUALIFIED_TYPE :
+ return QualifiedType.class;
+ case RETURN_STATEMENT :
+ return ReturnStatement.class;
+ case SIMPLE_NAME :
+ return SimpleName.class;
+ case SIMPLE_TYPE :
+ return SimpleType.class;
+ case SINGLE_VARIABLE_DECLARATION :
+ return SingleVariableDeclaration.class;
+ case STRING_LITERAL :
+ return StringLiteral.class;
+ case SUPER_CONSTRUCTOR_INVOCATION :
+ return SuperConstructorInvocation.class;
+ case SUPER_FIELD_ACCESS :
+ return SuperFieldAccess.class;
+ case SUPER_METHOD_INVOCATION :
+ return SuperMethodInvocation.class;
+ case SWITCH_CASE:
+ return SwitchCase.class;
+ case SWITCH_STATEMENT :
+ return SwitchStatement.class;
+ case TAG_ELEMENT :
+ return TagElement.class;
+ case TEXT_ELEMENT :
+ return TextElement.class;
+ case THIS_EXPRESSION :
+ return ThisExpression.class;
+ case THROW_STATEMENT :
+ return ThrowStatement.class;
+ case TRY_STATEMENT :
+ return TryStatement.class;
+ case TYPE_DECLARATION :
+ return TypeDeclaration.class;
+ case TYPE_DECLARATION_STATEMENT :
+ return TypeDeclarationStatement.class;
+ case TYPE_LITERAL :
+ return TypeLiteral.class;
+ case VARIABLE_DECLARATION_EXPRESSION :
+ return VariableDeclarationExpression.class;
+ case VARIABLE_DECLARATION_FRAGMENT :
+ return VariableDeclarationFragment.class;
+ case VARIABLE_DECLARATION_STATEMENT :
+ return VariableDeclarationStatement.class;
+ case WHILE_STATEMENT :
+ return WhileStatement.class;
+ case WITH_STATEMENT :
+ return WithStatement.class;
+ case OBJECT_LITERAL :
+ return ObjectLiteral.class;
+ case OBJECT_LITERAL_FIELD :
+ return ObjectLiteralField.class;
+ case FUNCTION_EXPRESSION :
+ return FunctionExpression.class;
+ case REGULAR_EXPRESSION_LITERAL :
+ return RegularExpressionLiteral.class;
+ case LIST_EXPRESSION :
+ return ListExpression.class;
+ }
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Owning AST.
+ *
+ * N.B. This ia a private field, but declared as package-visible
+ * for more efficient access from inner classes.
+ *
+ */
+ final AST ast;
+
+ /**
+ * Parent AST node, or null
if this node is a root.
+ * Initially null
.
+ */
+ private ASTNode parent = null;
+
+ /**
+ * An unmodifiable empty map (used to implement properties()
).
+ */
+ private static final Map UNMODIFIABLE_EMPTY_MAP
+ = Collections.unmodifiableMap(new HashMap(1));
+
+ /**
+ * Primary field used in representing node properties efficiently.
+ * If null
, this node has no properties.
+ * If a String
, this is the name of this node's sole property,
+ * and property2
contains its value.
+ * If a HashMap
, this is the table of property name-value
+ * mappings; property2
, if non-null is its unmodifiable
+ * equivalent.
+ * Initially null
.
+ *
+ * @see #property2
+ */
+ private Object property1 = null;
+
+ /**
+ * Auxillary field used in representing node properties efficiently.
+ *
+ * @see #property1
+ */
+ private Object property2 = null;
+
+ /**
+ * A character index into the original source string,
+ * or -1
if no source position information is available
+ * for this node; -1
by default.
+ */
+ private int startPosition = -1;
+
+ /**
+ * A character length, or 0
if no source position
+ * information is recorded for this node; 0
by default.
+ */
+ private int length = 0;
+
+ /**
+ * Flag constant (bit mask, value 1) indicating that there is something
+ * not quite right with this AST node.
+ *
+ * The standard parser (ASTParser
) sets this
+ * flag on a node to indicate a syntax error detected in the vicinity.
+ *
+ */
+ public static final int MALFORMED = 1;
+
+ /**
+ * Flag constant (bit mask, value 2) indicating that this is a node
+ * that was created by the parser (as opposed to one created by another
+ * party).
+ *
+ * The standard parser (ASTParser
) sets this
+ * flag on the nodes it creates.
+ *
+ *
+ */
+ public static final int ORIGINAL = 2;
+
+ /**
+ * Flag constant (bit mask, value 4) indicating that this node
+ * is unmodifiable. When a node is marked unmodifiable, the
+ * following operations result in a runtime exception:
+ *
+ * - Change a simple property of this node.
+ * - Add or remove a child node from this node.
+ * - Parent (or reparent) this node.
+ *
+ *
+ * The standard parser (ASTParser
) does not set
+ * this flag on the nodes it creates. However, clients may set
+ * this flag on a node to prevent further modification of the
+ * its structural properties.
+ *
+ */
+ public static final int PROTECT = 4;
+
+ /**
+ * Flag constant (bit mask, value 8) indicating that this node
+ * or a part of this node is recovered from source that contains
+ * a syntax error detected in the vicinity.
+ *
+ * The standard parser (ASTParser
) sets this
+ * flag on a node to indicate a recovered node.
+ *
+ */
+ public static final int RECOVERED = 8;
+
+ /**
+ * int containing the node type in the top 16 bits and
+ * flags in the bottom 16 bits; none set by default.
+ *
+ * N.B. This is a private field, but declared as package-visible
+ * for more efficient access from inner classes.
+ *
+ *
+ * @see #MALFORMED
+ */
+ int typeAndFlags = 0;
+
+ /**
+ * Property of parent in which this node is a child, or null
+ * if this node is a root. Initially null
.
+ *
+ * @see #getLocationInParent
+ */
+ private StructuralPropertyDescriptor location = null;
+
+ /** Internal convenience constant indicating that there is definite risk of cycles.
+ */
+ static final boolean CYCLE_RISK = true;
+
+ /** Internal convenience constant indicating that there is no risk of cycles.
+ */
+ static final boolean NO_CYCLE_RISK = false;
+
+ /** Internal convenience constant indicating that a structural property is mandatory.
+ */
+ static final boolean MANDATORY = true;
+
+ /** Internal convenience constant indicating that a structural property is optional.
+ */
+ static final boolean OPTIONAL = false;
+
+ /**
+ * A specialized implementation of a list of ASTNodes. The
+ * implementation is based on an ArrayList.
+ */
+ class NodeList extends AbstractList {
+
+ /**
+ * The underlying list in which the nodes of this list are
+ * stored (element type: ASTNode
).
+ *
+ * Be stingy on storage - assume that list will be empty.
+ *
+ *
+ * This field declared default visibility (rather than private)
+ * so that accesses from NodeList.Cursor
do not require
+ * a synthetic accessor method.
+ *
+ */
+ ArrayList store = new ArrayList(0);
+
+ /**
+ * The property descriptor for this list.
+ */
+ ChildListPropertyDescriptor propertyDescriptor;
+
+ /**
+ * A cursor for iterating over the elements of the list.
+ * Does not lose its position if the list is changed during
+ * the iteration.
+ */
+ class Cursor implements Iterator {
+ /**
+ * The position of the cursor between elements. If the value
+ * is N, then the cursor sits between the element at positions
+ * N-1 and N. Initially just before the first element of the
+ * list.
+ */
+ private int position = 0;
+
+ /* (non-Javadoc)
+ * Method declared on Iterator
.
+ */
+ public boolean hasNext() {
+ return this.position < NodeList.this.store.size();
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Iterator
.
+ */
+ public Object next() {
+ Object result = NodeList.this.store.get(this.position);
+ this.position++;
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Iterator
.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Adjusts this cursor to accomodate an add/remove at the given
+ * index.
+ *
+ * @param index the position at which the element was added
+ * or removed
+ * @param delta +1 for add, and -1 for remove
+ */
+ void update(int index, int delta) {
+ if (this.position > index) {
+ // the cursor has passed the added or removed element
+ this.position += delta;
+ }
+ }
+ }
+
+ /**
+ * A list of currently active cursors (element type:
+ * Cursor
), or null
if there are no
+ * active cursors.
+ *
+ * It is important for storage considerations to maintain the
+ * null-means-empty invariant; otherwise, every NodeList instance
+ * will waste a lot of space. A cursor is needed only for the duration
+ * of a visit to the child nodes. Under normal circumstances, only a
+ * single cursor is needed; multiple cursors are only required if there
+ * are multiple visits going on at the same time.
+ *
+ */
+ private List cursors = null;
+
+ /**
+ * Creates a new empty list of nodes owned by this node.
+ * This node will be the common parent of all nodes added to
+ * this list.
+ *
+ * @param property the property descriptor
+ */
+ NodeList(ChildListPropertyDescriptor property) {
+ super();
+ this.propertyDescriptor = property;
+ }
+
+ /* (non-javadoc)
+ * @see java.util.AbstractCollection#size()
+ */
+ public int size() {
+ return this.store.size();
+ }
+
+ /* (non-javadoc)
+ * @see AbstractList#get(int)
+ */
+ public Object get(int index) {
+ return this.store.get(index);
+ }
+
+ /* (non-javadoc)
+ * @see List#set(int, java.lang.Object)
+ */
+ public Object set(int index, Object element) {
+ if (element == null) {
+ throw new IllegalArgumentException();
+ }
+ if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ // delink old child from parent, and link new child to parent
+ ASTNode newChild = (ASTNode) element;
+ ASTNode oldChild = (ASTNode) this.store.get(index);
+ if (oldChild == newChild) {
+ return oldChild;
+ }
+ if ((oldChild.typeAndFlags & PROTECT) != 0) {
+ // old child is protected => cannot be unparented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
+ ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
+
+ Object result = this.store.set(index, newChild);
+ // n.b. setParent will call ast.modifying()
+ oldChild.setParent(null, null);
+ newChild.setParent(ASTNode.this, this.propertyDescriptor);
+ ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
+ return result;
+ }
+
+ /* (non-javadoc)
+ * @see List#add(int, java.lang.Object)
+ */
+ public void add(int index, Object element) {
+ if (element == null) {
+ // http://bugs.eclipse.org/255538 - Very frequent IllegalArgumentException in JSDT
+ // XXX: Workaround until we've gotten the AST corrected, silenty return
+ return;
+ //throw new IllegalArgumentException();
+ }
+ if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ // link new child to parent
+ ASTNode newChild = (ASTNode) element;
+ ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
+ ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
+
+
+ this.store.add(index, element);
+ updateCursors(index, +1);
+ // n.b. setParent will call ast.modifying()
+ newChild.setParent(ASTNode.this, this.propertyDescriptor);
+ ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
+ }
+
+ /* (non-javadoc)
+ * @see List#remove(int)
+ */
+ public Object remove(int index) {
+ if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ // delink old child from parent
+ ASTNode oldChild = (ASTNode) this.store.get(index);
+ if ((oldChild.typeAndFlags & PROTECT) != 0) {
+ // old child is protected => cannot be unparented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+
+ ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
+ // n.b. setParent will call ast.modifying()
+ oldChild.setParent(null, null);
+ Object result = this.store.remove(index);
+ updateCursors(index, -1);
+ ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
+ return result;
+
+ }
+
+ /**
+ * Allocate a cursor to use for a visit. The client must call
+ * releaseCursor
when done.
+ *
+ * This method is internally synchronized on this NodeList.
+ * It is thread-safe to create a cursor.
+ *
+ *
+ * @return a new cursor positioned before the first element
+ * of the list
+ */
+ Cursor newCursor() {
+ synchronized (this) {
+ // serialize cursor management on this NodeList
+ if (this.cursors == null) {
+ // convert null to empty list
+ this.cursors = new ArrayList(1);
+ }
+ Cursor result = new Cursor();
+ this.cursors.add(result);
+ return result;
+ }
+ }
+
+ /**
+ * Releases the given cursor at the end of a visit.
+ *
+ * This method is internally synchronized on this NodeList.
+ * It is thread-safe to release a cursor.
+ *
+ *
+ * @param cursor the cursor
+ */
+ void releaseCursor(Cursor cursor) {
+ synchronized (this) {
+ // serialize cursor management on this NodeList
+ this.cursors.remove(cursor);
+ if (this.cursors.isEmpty()) {
+ // important: convert empty list back to null
+ // otherwise the node will hang on to needless junk
+ this.cursors = null;
+ }
+ }
+ }
+
+ /**
+ * Adjusts all cursors to accomodate an add/remove at the given
+ * index.
+ *
+ * This method is only used when the list is being modified.
+ * The AST is not thread-safe if any of the clients are modifying it.
+ *
+ *
+ * @param index the position at which the element was added
+ * or removed
+ * @param delta +1 for add, and -1 for remove
+ */
+ private void updateCursors(int index, int delta) {
+ if (this.cursors == null) {
+ // there are no cursors to worry about
+ return;
+ }
+ for (Iterator it = this.cursors.iterator(); it.hasNext(); ) {
+ Cursor c = (Cursor) it.next();
+ c.update(index, delta);
+ }
+ }
+
+ /**
+ * Returns an estimate of the memory footprint of this node list
+ * instance in bytes.
+ *
+ * - 1 object header for the NodeList instance
+ * - 5 4-byte fields of the NodeList instance
+ * - 0 for cursors since null unless walk in progress
+ * - 1 object header for the ArrayList instance
+ * - 2 4-byte fields of the ArrayList instance
+ * - 1 object header for an Object[] instance
+ * - 4 bytes in array for each element
+ *
+ *
+ * @return the size of this node list in bytes
+ */
+ int memSize() {
+ int result = HEADERS + 5 * 4;
+ result += HEADERS + 2 * 4;
+ result += HEADERS + 4 * size();
+ return result;
+ }
+
+ /**
+ * Returns an estimate of the memory footprint in bytes of this node
+ * list and all its subtrees.
+ *
+ * @return the size of this list of subtrees in bytes
+ */
+ int listSize() {
+ int result = memSize();
+ for (Iterator it = iterator(); it.hasNext(); ) {
+ ASTNode child = (ASTNode) it.next();
+ result += child.treeSize();
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Creates a new AST node owned by the given AST. Once established,
+ * the relationship between an AST node and its owning AST does not change
+ * over the lifetime of the node. The new node has no parent node,
+ * and no properties.
+ *
+ * N.B. This constructor is package-private; all subclasses my be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ASTNode(AST ast) {
+ if (ast == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.ast = ast;
+ setNodeType(getNodeType0());
+ setFlags(ast.getDefaultNodeFlag());
+ // setFlags calls modifying();
+ }
+
+ /**
+ * Returns this node's AST.
+ *
+ * Note that the relationship between an AST node and its owing AST does
+ * not change over the lifetime of a node.
+ *
+ *
+ * @return the AST that owns this node
+ */
+ public final AST getAST() {
+ return this.ast;
+ }
+
+ /**
+ * Returns this node's parent node, or null
if this is the
+ * root node.
+ *
+ * Note that the relationship between an AST node and its parent node
+ * may change over the lifetime of a node.
+ *
+ *
+ * @return the parent of this node, or null
if none
+ */
+ public final ASTNode getParent() {
+ return this.parent;
+ }
+
+ /**
+ * Returns the location of this node within its parent,
+ * or null
if this is a root node.
+ *
+ *
+ * ASTNode node = ...;
+ * ASTNode parent = node.getParent();
+ * StructuralPropertyDescriptor location = node.getLocationInParent();
+ * assert (parent != null) == (location != null);
+ * if ((location != null) && location.isChildProperty())
+ * assert parent.getStructuralProperty(location) == node;
+ * if ((location != null) && location.isChildListProperty())
+ * assert ((List) parent.getStructuralProperty(location)).contains(node);
+ *
+ *
+ *
+ * Note that the relationship between an AST node and its parent node
+ * may change over the lifetime of a node.
+ *
+ *
+ * @return the location of this node in its parent,
+ * or null
if this node has no parent
+ */
+ public final StructuralPropertyDescriptor getLocationInParent() {
+ return this.location;
+ }
+
+ /**
+ * Returns the root node at or above this node; returns this node if
+ * it is a root.
+ *
+ * @return the root node at or above this node
+ */
+ public final ASTNode getRoot() {
+ ASTNode candidate = this;
+ while (true) {
+ ASTNode p = candidate.getParent();
+ if (p == null) {
+ // candidate has no parent - that's the guy
+ return candidate;
+ }
+ candidate = p;
+ }
+ }
+
+ /**
+ * Returns the value of the given structural property for this node. The value
+ * returned depends on the kind of property:
+ *
+ * - {@link SimplePropertyDescriptor} - the value of the given simple property,
+ * or
null
if none; primitive values are "boxed"
+ * - {@link ChildPropertyDescriptor} - the child node (type
ASTNode
),
+ * or null
if none
+ * - {@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})
+ *
+ *
+ * @param property the property
+ * @return the value, or null
if none
+ * @exception RuntimeException if this node does not have the given property
+ */
+ public final Object getStructuralProperty(StructuralPropertyDescriptor property) {
+ if (property instanceof SimplePropertyDescriptor) {
+ SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
+ if (p.getValueType() == int.class) {
+ int result = internalGetSetIntProperty(p, true, 0);
+ return new Integer(result);
+ } else if (p.getValueType() == boolean.class) {
+ boolean result = internalGetSetBooleanProperty(p, true, false);
+ return Boolean.valueOf(result);
+ } else {
+ return internalGetSetObjectProperty(p, true, null);
+ }
+ }
+ if (property instanceof ChildPropertyDescriptor) {
+ return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null);
+ }
+ if (property instanceof ChildListPropertyDescriptor) {
+ return internalGetChildListProperty((ChildListPropertyDescriptor) property);
+ }
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets the value of the given structural property for this node. The value
+ * passed depends on the kind of property:
+ *
+ * - {@link SimplePropertyDescriptor} - the new value of the given simple property,
+ * or
null
if none; primitive values are "boxed"
+ * - {@link ChildPropertyDescriptor} - the new child node (type
ASTNode
),
+ * or null
if none
+ * - {@link ChildListPropertyDescriptor} - not allowed
+ *
+ *
+ * @param property the property
+ * @param value the property value
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given property cannot be set
+ */
+ public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) {
+ if (property instanceof SimplePropertyDescriptor) {
+ SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
+ if (p.getValueType() == int.class) {
+ int arg = ((Integer) value).intValue();
+ internalGetSetIntProperty(p, false, arg);
+ return;
+ } else if (p.getValueType() == boolean.class) {
+ boolean arg = ((Boolean) value).booleanValue();
+ internalGetSetBooleanProperty(p, false, arg);
+ return;
+ } else {
+ if (value == null && p.isMandatory()) {
+ throw new IllegalArgumentException();
+ }
+ internalGetSetObjectProperty(p, false, value);
+ return;
+ }
+ }
+ if (property instanceof ChildPropertyDescriptor) {
+ ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
+ ASTNode child = (ASTNode) value;
+ if (child == null && p.isMandatory()) {
+ throw new IllegalArgumentException();
+ }
+ internalGetSetChildProperty(p, false, child);
+ return;
+ }
+ if (property instanceof ChildListPropertyDescriptor) {
+ throw new IllegalArgumentException("Cannot set the list of child list property"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets the value of the given int-valued property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one simple property whose value
+ * type is int.
+ *
+ * @param property the property
+ * @param get true
for a get operation, and
+ * false
for a set operation
+ * @param value the new property value; ignored for get operations
+ * @return the value; always returns
+ * 0
for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given value cannot be set as specified
+ *
+ */
+ int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the value of the given boolean-valued property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one simple property whose value
+ * type is boolean.
+ *
+ * @param property the property
+ * @param get true
for a get operation, and
+ * false
for a set operation
+ * @param value the new property value; ignored for get operations
+ * @return the value; always returns
+ * false
for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given value cannot be set as specified
+ */
+ boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the value of the given property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one simple property whose value
+ * type is a reference type.
+ *
+ * @param property the property
+ * @param get true
for a get operation, and
+ * false
for a set operation
+ * @param value the new property value, or null
if none;
+ * ignored for get operations
+ * @return the value, or null
if none; always returns
+ * null
for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given value cannot be set as specified
+ */
+ Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the child value of the given property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this node does not have such a property. This method should be
+ * extended in subclasses that have at leasy one child property.
+ *
+ * @param property the property
+ * @param get true
for a get operation, and
+ * false
for a set operation
+ * @param child the new child value, or null
if none;
+ * always null
for get operations
+ * @return the child, or null
if none; always returns
+ * null
for set operations
+ * @exception RuntimeException if this node does not have the
+ * given property, or if the given child cannot be set as specified
+ */
+ ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the list value of the given property for this node.
+ * The default implementation of this method throws an exception explaining
+ * that this noed does not have such a property. This method should be
+ * extended in subclasses that have at leasy one child list property.
+ *
+ * @param property the property
+ * @return the list (element type: {@link ASTNode})
+ * @exception RuntimeException if the given node does not have the
+ * given property
+ */
+ List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns a list of structural property descriptors for nodes of the
+ * same type as this node. Clients must not modify the result.
+ *
+ * Note that property descriptors are a meta-level mechanism
+ * for manipulating ASTNodes in a generic way. They are
+ * unrelated to get/setProperty
.
+ *
+ *
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public final List structuralPropertiesForType() {
+ return internalStructuralPropertiesForType(this.ast.apiLevel);
+ }
+
+ /**
+ * Returns a list of property descriptors for this node type.
+ * Clients must not modify the result. This abstract method
+ * must be implemented in each concrete AST node type.
+ *
+ * N.B. This method is package-private, so that the implementations
+ * of this method in each of the concrete AST node types do not
+ * clutter up the API doc.
+ *
+ *
+ * @param apiLevel the API level; one of the AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ abstract List internalStructuralPropertiesForType(int apiLevel);
+
+ /**
+ * Internal helper method that starts the building a list of
+ * property descriptors for the given node type.
+ *
+ * @param nodeClass the class for a concrete node type
+ * @param propertyList empty list
+ */
+ static void createPropertyList(Class nodeClass, List propertyList) {
+ // stuff nodeClass at head of list for future ref
+ propertyList.add(nodeClass);
+ }
+
+ /**
+ * Internal helper method that adding a property descriptor.
+ *
+ * @param property the structural property descriptor
+ * @param propertyList list beginning with the AST node class
+ * followed by accumulated structural property descriptors
+ */
+ static void addProperty(StructuralPropertyDescriptor property, List propertyList) {
+ Class nodeClass = (Class) propertyList.get(0);
+ if (property.getNodeClass() != nodeClass) {
+ // easily made cut-and-paste mistake
+ throw new RuntimeException("Structural property descriptor has wrong node class!"); //$NON-NLS-1$
+ }
+ propertyList.add(property);
+ }
+
+ /**
+ * Internal helper method that completes the building of
+ * a node type's structural property descriptor list.
+ *
+ * @param propertyList list beginning with the AST node class
+ * followed by accumulated structural property descriptors
+ * @return unmodifiable list of structural property descriptors
+ * (element type: StructuralPropertyDescriptor
)
+ */
+ static List reapPropertyList(List propertyList) {
+ propertyList.remove(0); // remove nodeClass
+ // compact
+ ArrayList a = new ArrayList(propertyList.size());
+ a.addAll(propertyList);
+ return Collections.unmodifiableList(a);
+ }
+
+ /**
+ * Checks that this AST operation is not used when
+ * building JLS2 level ASTs.
+
+ * @exception UnsupportedOperationException
+ */
+ final void unsupportedIn2() {
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Checks that this AST operation is only used when
+ * building JLS2 level ASTs.
+
+ * @exception UnsupportedOperationException
+ */
+ final void supportedOnlyIn2() {
+ if (this.ast.apiLevel != AST.JLS2_INTERNAL) {
+ throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets or clears this node's parent node and location.
+ *
+ * Note that this method is package-private. The pointer from a node
+ * to its parent is set implicitly as a side effect of inserting or
+ * removing the node as a child of another node. This method calls
+ * ast.modifying()
.
+ *
+ *
+ * @param parent the new parent of this node, or null
if none
+ * @param property the location of this node in its parent,
+ * or null
if parent
is null
+ * @see #getLocationInParent
+ * @see #getParent
+ */
+ final void setParent(ASTNode parent, StructuralPropertyDescriptor property) {
+ this.ast.modifying();
+ this.parent = parent;
+ this.location = property;
+ }
+
+ /**
+ * Removes this node from its parent. Has no effect if this node
+ * is unparented. If this node appears as an element of a child list
+ * property of its parent, then this node is removed from the
+ * list using List.remove
.
+ * If this node appears as the value of a child property of its
+ * parent, then this node is detached from its parent
+ * by passing null
to the appropriate setter method;
+ * this operation fails if this node is in a mandatory property.
+ *
+ */
+ public final void delete() {
+ StructuralPropertyDescriptor p = getLocationInParent();
+ if (p == null) {
+ // node is unparented
+ return;
+ }
+ if (p.isChildProperty()) {
+ getParent().setStructuralProperty(this.location, null);
+ return;
+ }
+ if (p.isChildListProperty()) {
+ List l = (List) getParent().getStructuralProperty(this.location);
+ l.remove(this);
+ }
+ }
+
+ /**
+ * Checks whether the given new child node is a node
+ * in a different AST from its parent-to-be, whether it is
+ * already has a parent, whether adding it to its
+ * parent-to-be would create a cycle, and whether the child is of
+ * the right type. The parent-to-be is the enclosing instance.
+ *
+ * @param node the parent-to-be node
+ * @param newChild the new child of the parent
+ * @param cycleCheck true
if cycles are possible and need
+ * to be checked, false
if cycles are impossible and do
+ * not need to be checked
+ * @param nodeType a type constraint on child nodes, or null
+ * if no special check is required
+ * @exception IllegalArgumentException if:
+ *
+ * - the child is null
+ * - the node belongs to a different AST
+ * - the child has the incorrect node type
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ static void checkNewChild(ASTNode node, ASTNode newChild,
+ boolean cycleCheck, Class nodeType) {
+ if (newChild.ast != node.ast) {
+ // new child is from a different AST
+ throw new IllegalArgumentException();
+ }
+ if (newChild.getParent() != null) {
+ // new child currently has a different parent
+ throw new IllegalArgumentException();
+ }
+ if (cycleCheck && newChild == node.getRoot()) {
+ // inserting new child would create a cycle
+ throw new IllegalArgumentException();
+ }
+ Class childClass = newChild.getClass();
+ if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
+ // new child is not of the right type
+
+ // fix for inner function handling, Etienne Pfister
+ if(!(newChild instanceof org.eclipse.wst.jsdt.core.dom.FunctionDeclaration)) {
+ throw new ClassCastException();
+ }
+ }
+ if ((newChild.typeAndFlags & PROTECT) != 0) {
+ // new child node is protected => cannot be parented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Prelude portion of the "3 step program" for replacing the
+ * old child of this node with another node.
+ * Here is the code pattern found in all AST node subclasses:
+ *
+ * ASTNode oldChild = this.foo;
+ * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
+ * this.foo = newFoo;
+ * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
+ *
+ * The first part (preReplaceChild) does all the precondition checks,
+ * reports pre-delete events, and changes parent links.
+ * The old child is delinked from its parent (making it a root node),
+ * and the new child node is linked to its parent. The new child node
+ * must be a root node in the same AST as its new parent, and must not
+ * be an ancestor of this node. All three nodes must be
+ * modifiable (not PROTECTED). The replace operation must fail
+ * atomically; so it is crucial that all precondition checks
+ * be done before any linking and delinking happens.
+ * The final part (postReplaceChild )reports post-add events.
+ *
+ * This method calls ast.modifying()
for the nodes affected.
+ *
+ *
+ * @param oldChild the old child of this node, or null
if
+ * there was no old child to replace
+ * @param newChild the new child of this node, or null
if
+ * there is no replacement child
+ * @param property the property descriptor of this node describing
+ * the relationship between node and child
+ * @exception RuntimeException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ * - any of the nodes involved are unmodifiable
+ *
+ */
+ final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
+ if ((this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot gain or lose children
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ if (newChild != null) {
+ checkNewChild(this, newChild, property.cycleRisk, null);
+ }
+ // delink old child from parent
+ if (oldChild != null) {
+ if ((oldChild.typeAndFlags & PROTECT) != 0) {
+ // old child node is protected => cannot be unparented
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ if (newChild != null) {
+ this.ast.preReplaceChildEvent(this, oldChild, newChild, property);
+ } else {
+ this.ast.preRemoveChildEvent(this, oldChild, property);
+ }
+ oldChild.setParent(null, null);
+ } else {
+ if(newChild != null) {
+ this.ast.preAddChildEvent(this, newChild, property);
+ }
+ }
+ // link new child to parent
+ if (newChild != null) {
+ newChild.setParent(this, property);
+ // cannot notify postAddChildEvent until parent is linked to child too
+ }
+ }
+
+ /**
+ * Postlude portion of the "3 step program" for replacing the
+ * old child of this node with another node.
+ * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
+ * for details.
+ */
+ final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
+ // link new child to parent
+ if (newChild != null) {
+ if (oldChild != null) {
+ this.ast.postReplaceChildEvent(this, oldChild, newChild, property);
+ } else {
+ this.ast.postAddChildEvent(this, newChild, property);
+ }
+ } else {
+ this.ast.postRemoveChildEvent(this, oldChild, property);
+ }
+ }
+
+ /**
+ * Prelude portion of the "3 step program" for changing the
+ * value of a simple property of this node.
+ * Here is the code pattern found in all AST node subclasses:
+ *
+ * preValueChange(FOO_PROPERTY);
+ * this.foo = newFoo;
+ * postValueChange(FOO_PROPERTY);
+ *
+ * The first part (preValueChange) does the precondition check
+ * to make sure the node is modifiable (not PROTECTED).
+ * The change operation must fail atomically; so it is crucial
+ * that the precondition checks are done before the field is
+ * hammered. The final part (postValueChange)reports post-change
+ * events.
+ *
+ * This method calls ast.modifying()
for the node affected.
+ *
+ *
+ * @param property the property descriptor of this node
+ * @exception RuntimeException if:
+ *
+ * - this node is unmodifiable
+ *
+ */
+ final void preValueChange(SimplePropertyDescriptor property) {
+ if ((this.typeAndFlags & PROTECT) != 0) {
+ // this node is protected => cannot change valure of properties
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ this.ast.preValueChangeEvent(this, property);
+ this.ast.modifying();
+ }
+
+ /**
+ * Postlude portion of the "3 step program" for replacing the
+ * old child of this node with another node.
+ * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
+ */
+ final void postValueChange(SimplePropertyDescriptor property) {
+ this.ast.postValueChangeEvent(this, property);
+ }
+
+ /**
+ * Ensures that this node is modifiable (that is, not marked PROTECTED).
+ * If successful, calls ast.modifying().
+ * @exception RuntimeException is not modifiable
+ */
+ final void checkModifiable() {
+ if ((this.typeAndFlags & PROTECT) != 0) {
+ throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+ }
+ this.ast.modifying();
+ }
+
+ /**
+ * Begin lazy initialization of this node.
+ * Here is the code pattern found in all AST
+ * node subclasses:
+ *
+ * if (this.foo == null) {
+ * // lazy init must be thread-safe for readers
+ * synchronized (this) {
+ * if (this.foo == null) {
+ * preLazyInit();
+ * this.foo = ...; // code to create new node
+ * postLazyInit(this.foo, FOO_PROPERTY);
+ * }
+ * }
+ * }
+ *
+ *
+ */
+ final void preLazyInit() {
+ // IMPORTANT: this method is called by readers
+ // ASTNode.this is locked at this point
+ this.ast.disableEvents();
+ // will turn events back on in postLasyInit
+ }
+
+ /**
+ * End lazy initialization of this node.
+ *
+ * @param newChild the new child of this node, or null
if
+ * there is no replacement child
+ * @param property the property descriptor of this node describing
+ * the relationship between node and child
+ */
+ final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) {
+ // IMPORTANT: this method is called by readers
+ // ASTNode.this is locked at this point
+ // newChild is brand new (so no chance of concurrent access)
+ newChild.setParent(this, property);
+ // turn events back on (they were turned off in corresponding preLazyInit)
+ this.ast.reenableEvents();
+ }
+
+ /**
+ * Returns the named property of this node, or null
if none.
+ *
+ * @param propertyName the property name
+ * @return the property value, or null
if none
+ * @see #setProperty(String,Object)
+ */
+ public final Object getProperty(String propertyName) {
+ if (propertyName == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.property1 == null) {
+ // node has no properties at all
+ return null;
+ }
+ if (this.property1 instanceof String) {
+ // node has only a single property
+ if (propertyName.equals(this.property1)) {
+ return this.property2;
+ } else {
+ return null;
+ }
+ }
+ // otherwise node has table of properties
+ Map m = (Map) this.property1;
+ return m.get(propertyName);
+ }
+
+ /**
+ * Sets the named property of this node to the given value,
+ * or to null
to clear it.
+ *
+ * Clients should employ property names that are sufficiently unique
+ * to avoid inadvertent conflicts with other clients that might also be
+ * setting properties on the same node.
+ *
+ *
+ * Note that modifying a property is not considered a modification to the
+ * AST itself. This is to allow clients to decorate existing nodes with
+ * their own properties without jeopardizing certain things (like the
+ * validity of bindings), which rely on the underlying tree remaining static.
+ *
+ *
+ * @param propertyName the property name
+ * @param data the new property value, or null
if none
+ * @see #getProperty(String)
+ */
+ public final void setProperty(String propertyName, Object data) {
+ if (propertyName == null) {
+ throw new IllegalArgumentException();
+ }
+ // N.B. DO NOT CALL ast.modifying();
+
+ if (this.property1 == null) {
+ // node has no properties at all
+ if (data == null) {
+ // we already know this
+ return;
+ }
+ // node gets its fist property
+ this.property1 = propertyName;
+ this.property2 = data;
+ return;
+ }
+
+ if (this.property1 instanceof String) {
+ // node has only a single property
+ if (propertyName.equals(this.property1)) {
+ // we're in luck
+ this.property2 = data;
+ if (data == null) {
+ // just deleted last property
+ this.property1 = null;
+ this.property2 = null;
+ }
+ return;
+ }
+ if (data == null) {
+ // we already know this
+ return;
+ }
+ // node already has one property - getting its second
+ // convert to more flexible representation
+ HashMap m = new HashMap(2);
+ m.put(this.property1, this.property2);
+ m.put(propertyName, data);
+ this.property1 = m;
+ this.property2 = null;
+ return;
+ }
+
+ // node has two or more properties
+ HashMap m = (HashMap) this.property1;
+ if (data == null) {
+ m.remove(propertyName);
+ // check for just one property left
+ if (m.size() == 1) {
+ // convert to more efficient representation
+ Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]);
+ this.property1 = entries[0].getKey();
+ this.property2 = entries[0].getValue();
+ }
+ return;
+ } else {
+ m.put(propertyName, data);
+ // still has two or more properties
+ return;
+ }
+ }
+
+ /**
+ * Returns an unmodifiable table of the properties of this node with
+ * non-null
values.
+ *
+ * @return the table of property values keyed by property name
+ * (key type: String
; value type: Object
)
+ */
+ public final Map properties() {
+ if (this.property1 == null) {
+ // node has no properties at all
+ return UNMODIFIABLE_EMPTY_MAP;
+ }
+ if (this.property1 instanceof String) {
+ // node has a single property
+ return Collections.singletonMap(this.property1, this.property2);
+ }
+
+ // node has two or more properties
+ if (this.property2 == null) {
+ this.property2 = Collections.unmodifiableMap((Map) this.property1);
+ }
+ // property2 is unmodifiable wrapper for map in property1
+ return (Map) this.property2;
+ }
+
+ /**
+ * Returns the flags associated with this node.
+ *
+ * No flags are associated with newly created nodes.
+ *
+ *
+ * The flags are the bitwise-or of individual flags.
+ * The following flags are currently defined:
+ *
+ * - {@link #MALFORMED} - indicates node is syntactically
+ * malformed
+ * - {@link #ORIGINAL} - indicates original node
+ * created by ASTParser
+ * - {@link #PROTECT} - indicates node is protected
+ * from further modification
+ * - {@link #RECOVERED} - indicates node or a part of this node
+ * is recovered from source that contains a syntax error
+ *
+ * Other bit positions are reserved for future use.
+ *
+ *
+ * @return the bitwise-or of individual flags
+ * @see #setFlags(int)
+ */
+ public final int getFlags() {
+ return this.typeAndFlags & 0xFFFF;
+ }
+
+ /**
+ * Sets the flags associated with this node to the given value.
+ *
+ * The flags are the bitwise-or of individual flags.
+ * The following flags are currently defined:
+ *
+ * - {@link #MALFORMED} - indicates node is syntactically
+ * malformed
+ * - {@link #ORIGINAL} - indicates original node
+ * created by ASTParser
+ * - {@link #PROTECT} - indicates node is protected
+ * from further modification
+ * - {@link #RECOVERED} - indicates node or a part of this node
+ * is recovered from source that contains a syntax error
+ *
+ * Other bit positions are reserved for future use.
+ *
+ *
+ * Note that the flags are not considered a structural
+ * property of the node, and can be changed even if the
+ * node is marked as protected.
+ *
+ *
+ * @param flags the bitwise-or of individual flags
+ * @see #getFlags()
+ */
+ public final void setFlags(int flags) {
+ this.ast.modifying();
+ int old = this.typeAndFlags & 0xFFFF0000;
+ this.typeAndFlags = old | (flags & 0xFFFF);
+ }
+
+ /**
+ * Returns an integer value identifying the type of this concrete AST node.
+ * The values are small positive integers, suitable for use in switch statements.
+ *
+ * For each concrete node type there is a unique node type constant (name
+ * and value). The unique node type constant for a concrete node type such as
+ * CastExpression
is ASTNode.CAST_EXPRESSION
.
+ *
+ *
+ * @return one of the node type constants
+ */
+ public final int getNodeType() {
+ return this.typeAndFlags >>> 16;
+ }
+
+ /**
+ * Sets the integer value identifying the type of this concrete AST node.
+ * The values are small positive integers, suitable for use in switch statements.
+ *
+ * @param nodeType one of the node type constants
+ */
+ private void setNodeType(int nodeType) {
+ int old = this.typeAndFlags & 0xFFFF0000;
+ this.typeAndFlags = old | (nodeType << 16);
+ }
+
+ /**
+ * Returns an integer value identifying the type of this concrete AST node.
+ *
+ * This internal method is implemented in each of the
+ * concrete node subclasses.
+ *
+ *
+ * @return one of the node type constants
+ */
+ abstract int getNodeType0();
+
+ /**
+ * The ASTNode
implementation of this Object
+ * method uses object identity (==). Use subtreeMatch
to
+ * compare two subtrees for equality.
+ *
+ * @param obj {@inheritDoc}
+ * @return {@inheritDoc}
+ * @see #subtreeMatch(ASTMatcher matcher, Object other)
+ */
+ public final boolean equals(Object obj) {
+ return this == obj; // equivalent to Object.equals
+ }
+
+ /*
+ * (non-Javadoc)
+ * This makes it consistent with the fact that a equals methods has been provided.
+ * @see java.lang.Object#hashCode()
+ */
+ public final int hashCode() {
+ return super.hashCode();
+ }
+
+ /**
+ * Returns whether the subtree rooted at the given node matches the
+ * given other object as decided by the given matcher.
+ *
+ * @param matcher the matcher
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match
+ */
+ public final boolean subtreeMatch(ASTMatcher matcher, Object other) {
+ return subtreeMatch0(matcher, other);
+ }
+
+ /**
+ * Returns whether the subtree rooted at the given node matches the
+ * given other object as decided by the given matcher.
+ *
+ * This internal method is implemented in each of the
+ * concrete node subclasses.
+ *
+ *
+ * @param matcher the matcher
+ * @param other the other object, or null
+ * @return true
if the subtree matches, or
+ * false
if they do not match
+ */
+ abstract boolean subtreeMatch0(ASTMatcher matcher, Object other);
+
+ /**
+ * Returns a deep copy of the subtree of AST nodes rooted at the
+ * given node. The resulting nodes are owned by the given AST,
+ * which may be different from the ASTs of the given node.
+ * Even if the given node has a parent, the result node will be unparented.
+ *
+ * Source range information on the original nodes is automatically copied to the new
+ * nodes. Client properties (properties
) are not carried over.
+ *
+ *
+ * The node's AST
and the target AST
must support
+ * the same API level.
+ *
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @param node the node to copy, or null
if none
+ * @return the copied node, or null
if node
+ * is null
+ */
+ public static ASTNode copySubtree(AST target, ASTNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (target == null) {
+ throw new IllegalArgumentException();
+ }
+ if (target.apiLevel() != node.getAST().apiLevel()) {
+ throw new UnsupportedOperationException();
+ }
+ ASTNode newNode = node.clone(target);
+ return newNode;
+ }
+
+ /**
+ * Returns a deep copy of the subtrees of AST nodes rooted at the
+ * given list of nodes. The resulting nodes are owned by the given AST,
+ * which may be different from the ASTs of the nodes in the list.
+ * Even if the nodes in the list have parents, the nodes in the result
+ * will be unparented.
+ *
+ * Source range information on the original nodes is automatically copied to the new
+ * nodes. Client properties (properties
) are not carried over.
+ *
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @param nodes the list of nodes to copy
+ * (element type: ASTNode
)
+ * @return the list of copied subtrees
+ * (element type: ASTNode
)
+ */
+ public static List copySubtrees(AST target, List nodes) {
+ List result = new ArrayList(nodes.size());
+ for (Iterator it = nodes.iterator(); it.hasNext(); ) {
+ ASTNode oldNode = (ASTNode) it.next();
+ ASTNode newNode = oldNode.clone(target);
+ result.add(newNode);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a deep copy of the subtree of AST nodes rooted at this node.
+ * The resulting nodes are owned by the given AST, which may be different
+ * from the AST of this node. Even if this node has a parent, the
+ * result node will be unparented.
+ *
+ * This method reports pre- and post-clone events, and dispatches
+ * to clone0(AST)
which is reimplemented in node subclasses.
+ *
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @return the root node of the copies subtree
+ */
+ final ASTNode clone(AST target) {
+ this.ast.preCloneNodeEvent(this);
+ ASTNode c = this.clone0(target);
+ this.ast.postCloneNodeEvent(this, c);
+ return c;
+ }
+
+ /**
+ * Returns a deep copy of the subtree of AST nodes rooted at this node.
+ * The resulting nodes are owned by the given AST, which may be different
+ * from the AST of this node. Even if this node has a parent, the
+ * result node will be unparented.
+ *
+ * This method must be implemented in subclasses.
+ *
+ *
+ * This method does not report pre- and post-clone events.
+ * All callers should instead call clone(AST)
+ * to ensure that pre- and post-clone events are reported.
+ *
+ *
+ * N.B. This method is package-private, so that the implementations
+ * of this method in each of the concrete AST node types do not
+ * clutter up the API doc.
+ *
+ *
+ * @param target the AST that is to own the nodes in the result
+ * @return the root node of the copies subtree
+ */
+ abstract ASTNode clone0(AST target);
+
+ /**
+ * Accepts the given visitor on a visit of the current node.
+ *
+ * @param visitor the visitor object
+ * @exception IllegalArgumentException if the visitor is null
+ */
+ public final void accept(ASTVisitor visitor) {
+ if (visitor == null) {
+ throw new IllegalArgumentException();
+ }
+ // begin with the generic pre-visit
+ visitor.preVisit(this);
+ // dynamic dispatch to internal method for type-specific visit/endVisit
+ accept0(visitor);
+ // end with the generic post-visit
+ visitor.postVisit(this);
+ }
+
+ /**
+ * Accepts the given visitor on a type-specific visit of the current node.
+ * This method must be implemented in all concrete AST node types.
+ *
+ * General template for implementation on each concrete ASTNode class:
+ *
+ *
+ * boolean visitChildren = visitor.visit(this);
+ * if (visitChildren) {
+ * // visit children in normal left to right reading order
+ * acceptChild(visitor, getProperty1());
+ * acceptChildren(visitor, rawListProperty);
+ * acceptChild(visitor, getProperty2());
+ * }
+ * visitor.endVisit(this);
+ *
+ *
+ * Note that the caller (accept
) take cares of invoking
+ * visitor.preVisit(this)
and visitor.postVisit(this)
.
+ *
+ *
+ * @param visitor the visitor object
+ */
+ abstract void accept0(ASTVisitor visitor);
+
+ /**
+ * Accepts the given visitor on a visit of the current node.
+ *
+ * This method should be used by the concrete implementations of
+ * accept0
to traverse optional properties. Equivalent
+ * to child.accept(visitor)
if child
+ * is not null
.
+ *
+ *
+ * @param visitor the visitor object
+ * @param child the child AST node to dispatch too, or null
+ * if none
+ */
+ final void acceptChild(ASTVisitor visitor, ASTNode child) {
+ if (child == null) {
+ return;
+ }
+ child.accept(visitor);
+ }
+
+ /**
+ * Accepts the given visitor on a visit of the given live list of
+ * child nodes.
+ *
+ * This method must be used by the concrete implementations of
+ * accept
to traverse list-values properties; it
+ * encapsulates the proper handling of on-the-fly changes to the list.
+ *
+ *
+ * @param visitor the visitor object
+ * @param children the child AST node to dispatch too, or null
+ * if none
+ */
+ final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) {
+ if(children == null){
+ return;
+ }
+ // use a cursor to keep track of where we are up to
+ // (the list may be changing under foot)
+ NodeList.Cursor cursor = children.newCursor();
+ try {
+ while (cursor.hasNext()) {
+ ASTNode child = (ASTNode) cursor.next();
+ child.accept(visitor);
+ }
+ } finally {
+ children.releaseCursor(cursor);
+ }
+ }
+
+ /**
+ * Returns the character index into the original source file indicating
+ * where the source fragment corresponding to this node begins.
+ *
+ * The parser supplies useful well-defined source ranges to the nodes it creates.
+ * See {@link ASTParser#setKind(int)} for details
+ * on precisely where source ranges begin and end.
+ *
+ *
+ * @return the 0-based character index, or -1
+ * if no source position information is recorded for this node
+ * @see #getLength()
+ * @see ASTParser
+ */
+ public final int getStartPosition() {
+ return this.startPosition;
+ }
+
+ /**
+ * Returns the length in characters of the original source file indicating
+ * where the source fragment corresponding to this node ends.
+ *
+ * The parser supplies useful well-defined source ranges to the nodes it creates.
+ * See {@link ASTParser#setKind(int)} methods for details
+ * on precisely where source ranges begin and end.
+ *
+ *
+ * @return a (possibly 0) length, or 0
+ * if no source position information is recorded for this node
+ * @see #getStartPosition()
+ * @see ASTParser
+ */
+ public final int getLength() {
+ return this.length;
+ }
+
+ /**
+ * Sets the source range of the original source file where the source
+ * fragment corresponding to this node was found.
+ *
+ * See {@link ASTParser#setKind(int)} for details
+ * on precisely where source ranges are supposed to begin and end.
+ *
+ *
+ * @param startPosition a 0-based character index,
+ * or -1
if no source position information is
+ * available for this node
+ * @param length a (possibly 0) length,
+ * or 0
if no source position information is recorded
+ * for this node
+ * @see #getStartPosition()
+ * @see #getLength()
+ * @see ASTParser
+ */
+ public final void setSourceRange(int startPosition, int length) {
+ if (startPosition >= 0 && length < 0) {
+ throw new IllegalArgumentException();
+ }
+ if (startPosition < 0 && length != 0) {
+ throw new IllegalArgumentException();
+ }
+ // source positions are not considered a structural property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.startPosition = startPosition;
+ this.length = length;
+ }
+
+ /**
+ * Returns a string representation of this node suitable for debugging
+ * purposes only.
+ *
+ * @return a debug string
+ */
+ public final String toString() {
+ StringBuffer buffer = new StringBuffer();
+ int p = buffer.length();
+ try {
+ appendDebugString(buffer);
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ // since debugger sometimes call toString methods, problems can easily happen when
+ // toString is called on an instance that is being initialized
+ buffer.setLength(p);
+ buffer.append("!"); //$NON-NLS-1$
+ buffer.append(standardToString());
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the string representation of this node produced by the standard
+ * Object.toString
method.
+ *
+ * @return a debug string
+ */
+ final String standardToString() {
+ return super.toString();
+ }
+
+ /**
+ * Appends a debug representation of this node to the given string buffer.
+ *
+ * The ASTNode
implementation of this method prints out the entire
+ * subtree. Subclasses may override to provide a more succinct representation.
+ *
+ *
+ * @param buffer the string buffer to append to
+ */
+ void appendDebugString(StringBuffer buffer) {
+ // print the subtree by default
+ appendPrintString(buffer);
+ }
+
+ /**
+ * Appends a standard JavaScript source code representation of this subtree to the given
+ * string buffer.
+ *
+ * @param buffer the string buffer to append to
+ */
+ final void appendPrintString(StringBuffer buffer) {
+ NaiveASTFlattener printer = new NaiveASTFlattener();
+ this.accept(printer);
+ buffer.append(printer.getResult());
+ }
+
+ /**
+ * Estimate of size of an object header in bytes.
+ */
+ static final int HEADERS = 12;
+
+ /**
+ * Approximate base size of an AST node instance in bytes,
+ * including object header and instance fields.
+ * That is, HEADERS + (# instance vars in ASTNode)*4.
+ */
+ static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
+
+ /**
+ * Returns an estimate of the memory footprint, in bytes,
+ * of the given string.
+ *
+ * @param string the string to measure, or null
+ * @return the size of this string object in bytes, or
+ * 0 if the string is null
+ */
+ static int stringSize(String string) {
+ int size = 0;
+ if (string != null) {
+ // Strings usually have 4 instance fields, one of which is a char[]
+ size += HEADERS + 4 * 4;
+ // char[] has 2 bytes per character
+ size += HEADERS + 2 * string.length();
+ }
+ return size;
+ }
+
+ /**
+ * Returns an estimate of the memory footprint in bytes of the entire
+ * subtree rooted at this node.
+ *
+ * @return the size of this subtree in bytes
+ */
+ public final int subtreeBytes() {
+ return treeSize();
+ }
+
+ /**
+ * Returns an estimate of the memory footprint in bytes of the entire
+ * subtree rooted at this node.
+ *
+ * N.B. This method is package-private, so that the implementations
+ * of this method in each of the concrete AST node types do not
+ * clutter up the API doc.
+ *
+ *
+ * @return the size of this subtree in bytes
+ */
+ abstract int treeSize();
+
+ /**
+ * Returns an estimate of the memory footprint of this node in bytes.
+ * The estimate does not include the space occupied by child nodes.
+ *
+ * @return the size of this node in bytes
+ */
+ abstract int memSize();
+
+ public ASTNode getBodyChild()
+ {
+ ASTNode bodyChild=this;
+ while (bodyChild!=null)
+ {
+ if (bodyChild.parent instanceof JavaScriptUnit || bodyChild.parent instanceof BodyDeclaration)
+ return bodyChild;
+ bodyChild=bodyChild.parent;
+ }
+ return null;
+
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTParser.java
new file mode 100644
index 0000000..1d7e542
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTParser.java
@@ -0,0 +1,1161 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.jsdt.core.IClassFile;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.ITypeRoot;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.core.BasicCompilationUnit;
+import org.eclipse.wst.jsdt.internal.core.DefaultWorkingCopyOwner;
+import org.eclipse.wst.jsdt.internal.core.PackageFragment;
+import org.eclipse.wst.jsdt.internal.core.util.CodeSnippetParsingUtil;
+import org.eclipse.wst.jsdt.internal.core.util.RecordedParsingInformation;
+import org.eclipse.wst.jsdt.internal.core.util.Util;
+
+/**
+ * A JavaScript language parser for creating abstract syntax trees (ASTs).
+ *
+ * Example: Create basic AST from source string
+ *
+ * char[] source = ...;
+ * ASTParser parser = ASTParser.newParser(AST.JLS3);
+ * parser.setSource(source);
+ * JavaScriptUnit result = (JavaScriptUnit) parser.createAST(null);
+ *
+ * Once a configured parser instance has been used to create an AST,
+ * the settings are automatically reset to their defaults,
+ * ready for the parser instance to be reused.
+ *
+ *
+ * There are a number of configurable features:
+ *
+ * - Source string from {@link #setSource(char[]) char[]},
+ * {@link #setSource(IJavaScriptUnit) IJavaScriptUnit},
+ * or {@link #setSource(IClassFile) IClassFile}, and limited
+ * to a specified {@linkplain #setSourceRange(int,int) subrange}.
+ * - Whether {@linkplain #setResolveBindings(boolean) bindings} will be created.
+ * - Which {@linkplain #setWorkingCopyOwner(WorkingCopyOwner)
+ * working set owner} to use when resolving bindings).
+ * - A hypothetical {@linkplain #setUnitName(String) javaScript unit file name}
+ * and {@linkplain #setProject(IJavaScriptProject) JavaScript project}
+ * for locating a raw source string in the JavaScript model (when
+ * resolving bindings)
+ * - Which {@linkplain #setCompilerOptions(Map) validator options}
+ * to use.
+ * - Whether to parse just {@linkplain #setKind(int) an expression, statements,
+ * or body declarations} rather than an entire javaScript unit.
+ * - Whether to return a {@linkplain #setFocalPosition(int) abridged AST}
+ * focused on the declaration containing a given source position.
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ASTParser {
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a single expression.
+ */
+ public static final int K_EXPRESSION = 0x01;
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a sequence of statements.
+ */
+ public static final int K_STATEMENTS = 0x02;
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a sequence of class body declarations.
+ */
+ public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
+
+ /**
+ * Kind constant used to request that the source be parsed
+ * as a javaScript unit.
+ */
+ public static final int K_COMPILATION_UNIT = 0x08;
+
+ /**
+ * Creates a new object for creating a JavaScript abstract syntax tree
+ * (AST) following the specified set of API rules.
+ *
+ * @param level the API level; one of the LEVEL constants
+ * declared on AST
+ * @return new ASTParser instance
+ */
+ public static ASTParser newParser(int level) {
+ return new ASTParser(level);
+ }
+
+ /**
+ * Level of AST API desired.
+ */
+ private final int apiLevel;
+
+ /**
+ * Kind of parse requested. Defaults to an entire javaScript unit.
+ */
+ private int astKind;
+
+ /**
+ * Compiler options. Defaults to JavaScriptCore.getOptions().
+ */
+ private Map compilerOptions;
+
+ /**
+ * Request for bindings. Defaults to false
.
+ */
+ private boolean resolveBindings;
+
+ /**
+ * Request for a partial AST. Defaults to false
.
+ */
+ private boolean partial = false;
+
+ /**
+ * Request for a statements recovery. Defaults to false
.
+ */
+ private boolean statementsRecovery;
+
+ /**
+ * Request for a bindings recovery. Defaults to false
.
+ */
+ private boolean bindingsRecovery;
+
+
+ /**
+ * The focal point for a partial AST request.
+ * Only used when partial
is true
.
+ */
+ private int focalPointPosition;
+
+ /**
+ * Source string.
+ */
+ private char[] rawSource = null;
+
+ /**
+ * JavaScript unit supplying the source.
+ */
+ private ITypeRoot typeRoot = null;
+
+ /**
+ * Character-based offset into the source string where parsing is to
+ * begin. Defaults to 0.
+ */
+ private int sourceOffset = 0;
+
+ /**
+ * Character-based length limit, or -1 if unlimited.
+ * All characters in the source string between offset
+ * and offset+length-1
inclusive are parsed. Defaults to -1,
+ * which means the rest of the source string.
+ */
+ private int sourceLength = -1;
+
+ /**
+ * Working copy owner. Defaults to primary owner.
+ */
+ private WorkingCopyOwner workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+
+ /**
+ * JavaScript project used to resolve names, or null
if none.
+ * Defaults to none.
+ */
+ private IJavaScriptProject project = null;
+
+ /**
+ * Name of the javaScript unit for resolving bindings, or
+ * null
if none. Defaults to none.
+ */
+ private String unitName = null;
+
+ /**
+ * Creates a new AST parser for the given API level.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param level the API level; one of the LEVEL constants
+ * declared on AST
+ */
+ ASTParser(int level) {
+ if ((level != AST.JLS2_INTERNAL)
+ && (level != AST.JLS3)) {
+ throw new IllegalArgumentException();
+ }
+ this.apiLevel = level;
+ initializeDefaults();
+ }
+
+ /**
+ * Sets all the setting to their default values.
+ */
+ private void initializeDefaults() {
+ this.astKind = K_COMPILATION_UNIT;
+ this.rawSource = null;
+ this.typeRoot = null;
+ this.resolveBindings = false;
+ this.sourceLength = -1;
+ this.sourceOffset = 0;
+ this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+ this.unitName = null;
+ this.project = null;
+ this.partial = false;
+ Map options = JavaScriptCore.getOptions();
+ options.remove(JavaScriptCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+
+ /**
+ * Requests that the validator should perform bindings recovery.
+ * When bindings recovery is enabled the validator returns incomplete bindings.
+ *
+ * Default to false
.
+ *
+ * This should be set to true only if bindings are resolved. It has no effect if there is no binding
+ * resolution.
+ *
+ * @param enabled true
if incomplete bindings are expected,
+ * and false
if only complete bindings are expected.
+ *
+ * @see IBinding#isRecovered()
+ */
+ public void setBindingsRecovery(boolean enabled) {
+ this.bindingsRecovery = enabled;
+ }
+
+ /**
+ * Sets the validator options to be used when parsing.
+ *
+ * Note that {@link #setSource(IClassFile)},
+ * {@link #setSource(IJavaScriptUnit)},
+ * and {@link #setProject(IJavaScriptProject)} reset the validator options
+ * based on the JavaScript project. In other cases, validator options default
+ * to {@link JavaScriptCore#getOptions()}. In either case, and especially
+ * in the latter, the caller should carefully weight the consequences of
+ * allowing validator options to be defaulted as opposed to being
+ * explicitly specified for the ASTParser
instance.
+ * For instance, there is a validator option called "Source Compatibility Mode"
+ * which determines which JDK level the source code is expected to meet.
+ * If you specify "1.4", then "assert" is treated as a keyword and disallowed
+ * as an identifier; if you specify "1.3", then "assert" is allowed as an
+ * identifier. So this particular setting has a major bearing on what is
+ * considered syntactically legal. By explicitly specifying the setting,
+ * the client control exactly how the parser works. On the other hand,
+ * allowing default settings means the parsing behaves like other JDT tools.
+ *
+ *
+ * @param options the table of options (key type: String
;
+ * value type: String
), or null
+ * to set it back to the default
+ */
+ public void setCompilerOptions(Map options) {
+ if (options == null) {
+ options = JavaScriptCore.getOptions();
+ } else {
+ // copy client's options so as to not do any side effect on them
+ options = new HashMap(options);
+ }
+ options.remove(JavaScriptCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+
+ /**
+ * Requests that the validator should provide binding information for
+ * the AST nodes it creates.
+ *
+ * Default to false
(no bindings).
+ *
+ *
+ * If setResolveBindings(true)
, the various names
+ * and types appearing in the AST can be resolved to "bindings"
+ * by calling the resolveBinding
methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * resolveBinding
methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If setResolveBindings(false)
(the default), the analysis
+ * does not go beyond parsing and building the tree, and all
+ * resolveBinding
methods return null
from the
+ * outset.
+ *
+ *
+ * When bindings are requested, instead of considering javaScript units on disk only
+ * one can supply a WorkingCopyOwner
. Working copies owned
+ * by this owner take precedence over the underlying javaScript units when looking
+ * up names and drawing the connections.
+ *
+ *
+ * Binding information is obtained from the JavaScript model.
+ * This means that the javaScript unit must be located relative to the
+ * JavaScript model. This happens automatically when the source code comes from
+ * either {@link #setSource(IJavaScriptUnit) setSource(IJavaScriptUnit)}
+ * or {@link #setSource(IClassFile) setSource(IClassFile)}.
+ * When source is supplied by {@link #setSource(char[]) setSource(char[])},
+ * the location must be extablished explicitly by calling
+ * {@link #setProject(IJavaScriptProject)} and {@link #setUnitName(String)}.
+ * Note that the validator options that affect doc comment checking may also
+ * affect whether any bindings are resolved for nodes within doc comments.
+ *
+ *
+ * @param bindings true
if bindings are wanted,
+ * and false
if bindings are not of interest
+ */
+ public void setResolveBindings(boolean bindings) {
+ this.resolveBindings = bindings;
+ }
+
+ /**
+ * Requests an abridged abstract syntax tree.
+ * By default, complete ASTs are returned.
+ *
+ * When true
the resulting AST does not have nodes for
+ * the entire javaScript unit. Rather, the AST is only fleshed out
+ * for the node that include the given source position. This kind of limited
+ * AST is sufficient for certain purposes but totally unsuitable for others.
+ * In places where it can be used, the limited AST offers the advantage of
+ * being smaller and faster to construct.
+ *
+ *
+ * The AST will include nodes for all of the javaScript unit's functions, top-level vars,
+ * package, import, and top-level type declarations. It will also always contain
+ * nodes for all the body declarations for those top-level types, as well
+ * as body declarations for any member types. However, some of the body
+ * declarations may be abridged. In particular, the statements ordinarily
+ * found in the body of a method declaration node will not be included
+ * (the block will be empty) unless the source position falls somewhere
+ * within the source range of that method declaration node. The same is true
+ * for initializer declarations; the statements ordinarily found in the body
+ * of initializer node will not be included unless the source position falls
+ * somewhere within the source range of that initializer declaration node.
+ * Field declarations are never abridged. Note that the AST for the body of
+ * that one unabridged method (or initializer) is 100% complete; it has all
+ * its statements, including any local or anonymous type declarations
+ * embedded within them. When the the given position is not located within
+ * the source range of any body declaration of a top-level type, the AST
+ * returned will be a skeleton that includes nodes for all and only the major
+ * declarations; this kind of AST is still quite useful because it contains
+ * all the constructs that introduce names visible to the world outside the
+ * javaScript unit.
+ *
+ *
+ * @param position a position into the corresponding body declaration
+ */
+ public void setFocalPosition(int position) {
+ this.partial = true;
+ this.focalPointPosition = position;
+ }
+
+ /**
+ * Sets the kind of constructs to be parsed from the source.
+ * Defaults to an entire javaScript unit.
+ *
+ * When the parse is successful the result returned includes the ASTs for the
+ * requested source:
+ *
+ * - {@link #K_JAVASCRIPT_UNIT K_JAVASCRIPT_UNIT}: The result node
+ * is a {@link JavaScriptUnit}.
+ * - {@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
+ * is a {@link TypeDeclaration} whose
+ * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
+ * are the new trees. Other aspects of the type declaration are unspecified.
+ * - {@link #K_STATEMENTS K_STATEMENTS}: The result node is a
+ * {@link Block Block} whose {@link Block#statements() statements}
+ * are the new trees. Other aspects of the block are unspecified.
+ * - {@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
+ * {@link Expression Expression}. Other aspects of the expression are unspecified.
+ *
+ * The resulting AST node is rooted under (possibly contrived)
+ * {@link JavaScriptUnit JavaScriptUnit} node, to allow the
+ * client to retrieve the following pieces of information
+ * available there:
+ *
+ * - {@linkplain JavaScriptUnit#getLineNumber(int) Line number map}. Line
+ * numbers start at 1 and only cover the subrange scanned
+ * (
source[offset]
through source[offset+length-1]
).
+ * - {@linkplain JavaScriptUnit#getMessages() Compiler messages}
+ * and {@linkplain JavaScriptUnit#getProblems() detailed problem reports}.
+ * Character positions are relative to the start of
+ *
source
; line positions are for the subrange scanned.
+ * - {@linkplain JavaScriptUnit#getCommentList() Comment list}
+ * for the subrange scanned.
+ *
+ * The contrived nodes do not have source positions. Other aspects of the
+ * {@link JavaScriptUnit JavaScriptUnit} node are unspecified, including
+ * the exact arrangment of intervening nodes.
+ *
+ *
+ * Lexical or syntax errors detected while parsing can result in
+ * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
+ * In more severe failure cases where the parser is unable to
+ * recognize the input, this method returns
+ * a {@link JavaScriptUnit JavaScriptUnit} node with at least the
+ * validator messages.
+ *
+ * Each node in the subtree (other than the contrived nodes)
+ * carries source range(s) information relating back
+ * to positions in the given source (the given source itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ *
+ *
+ * Binding information is only computed when kind
is
+ * K_JAVASCRIPT_UNIT
.
+ *
+ *
+ * @param kind the kind of construct to parse: one of
+ * {@link #K_JAVASCRIPT_UNIT},
+ * {@link #K_CLASS_BODY_DECLARATIONS},
+ * {@link #K_EXPRESSION},
+ * {@link #K_STATEMENTS}
+ */
+ public void setKind(int kind) {
+ if ((kind != K_COMPILATION_UNIT)
+ && (kind != K_CLASS_BODY_DECLARATIONS)
+ && (kind != K_EXPRESSION)
+ && (kind != K_STATEMENTS)) {
+ throw new IllegalArgumentException();
+ }
+ this.astKind = kind;
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ *
+ * @param source the source string to be parsed,
+ * or null
if none
+ */
+ public void setSource(char[] source) {
+ this.rawSource = source;
+ // clear the type root
+ this.typeRoot = null;
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ * This method automatically sets the project (and compiler
+ * options) based on the given javaScript unit, in a manner
+ * equivalent to setProject(source.getJavaProject())
+ *
+ * @param source the JavaScript model javaScript unit whose source code
+ * is to be parsed, or null
if none
+ */
+ public void setSource(IJavaScriptUnit source) {
+ setSource((ITypeRoot)source);
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ * This method automatically sets the project (and compiler
+ * options) based on the given javaScript unit, in a manner
+ * equivalent to setProject(source.getJavaProject())
.
+ *
+ * @param source the JavaScript file whose corresponding source code
+ * is to be parsed, or null
if none
+ */
+ public void setSource(IClassFile source) {
+ setSource((ITypeRoot)source);
+ }
+
+ /**
+ * Sets the source code to be parsed.
+ * This method automatically sets the project (and compiler
+ * options) based on the given javaScript unit, in a manner
+ * equivalent to setProject(source.getJavaProject())
.
+ *
+ * @param source the JavaScript model javaScript unit whose corresponding source code
+ * is to be parsed, or null
if none
+ */
+ public void setSource(ITypeRoot source) {
+ this.typeRoot = source;
+ // clear the raw source
+ this.rawSource = null;
+ if (source != null) {
+ this.project = source.getJavaScriptProject();
+ Map options = this.project.getOptions(true);
+ options.remove(JavaScriptCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+ }
+
+ /**
+ * Sets the subrange of the source code to be parsed.
+ * By default, the entire source string will be parsed
+ * (offset
0 and length
-1).
+ *
+ * @param offset the index of the first character to parse
+ * @param length the number of characters to parse, or -1 if
+ * the remainder of the source string is
+ */
+ public void setSourceRange(int offset, int length) {
+ if (offset < 0 || length < -1) {
+ throw new IllegalArgumentException();
+ }
+ this.sourceOffset = offset;
+ this.sourceLength = length;
+ }
+
+ /**
+ * Requests that the validator should perform statements recovery.
+ * When statements recovery is enabled the validator tries to create statement nodes
+ * from code containing syntax errors
+ *
+ * Default to false
.
+ *
+ *
+ * @param enabled true
if statements containing syntax errors are wanted,
+ * and false
if these statements aren't wanted.
+ *
+ */
+ public void setStatementsRecovery(boolean enabled) {
+ this.statementsRecovery = enabled;
+ }
+
+ /**
+ * Sets the working copy owner using when resolving bindings, where
+ * null
means the primary owner. Defaults to the primary owner.
+ *
+ * @param owner the owner of working copies that take precedence over underlying
+ * javaScript units, or null
if the primary owner should be used
+ */
+ public void setWorkingCopyOwner(WorkingCopyOwner owner) {
+ if (owner == null) {
+ this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+ } else {
+ this.workingCopyOwner = owner;
+ }
+ }
+
+ /**
+ * Sets the name of the javaScript unit that would hypothetically contains
+ * the source string. This is used in conjunction with {@link #setSource(char[])}
+ * and {@link #setProject(IJavaScriptProject) } to locate the javaScript unit relative to a JavaScript project.
+ * Defaults to none (null
).
+ *
+ * The name of the javaScript unit must be supplied for resolving bindings.
+ * This name should be suffixed by a dot ('.') followed by one of the
+ * {@link JavaScriptCore#getJavaScriptLikeExtensions() JavaScript-like extensions}.
+ *
+ *
This name must represent the full path of the unit inside the given project. For example, if the source
+ * declares a public class named "Foo" in a project "P", the name of the javaScript unit must be
+ * "/P/Foo.js". If the source declares a public class name "Bar" in a package "p1.p2" in a project "P",
+ * the name of the javaScript unit must be "/P/p1/p2/Bar.js".
+ *
+ * @param unitName the name of the javaScript unit that would contain the source
+ * string, or null
if none
+ */
+ public void setUnitName(String unitName) {
+ this.unitName = unitName;
+ }
+
+ /**
+ * Sets the JavaScript project used when resolving bindings.
+ * This method automatically sets the compiler
+ * options based on the given project:
+ *
+ * setCompilerOptions(project.getOptions(true));
+ *
+ * See {@link #setCompilerOptions(Map)} for a discussion of
+ * the pros and cons of using these options vs specifying
+ * validator options explicitly.
+ * This setting is used in conjunction with setSource(char[])
.
+ * For the purposes of resolving bindings, types declared in the
+ * source string will hide types by the same name available
+ * through the includepath of the given project.
+ * Defaults to none (null
).
+ *
+ * @param project the JavaScript project used to resolve names, or
+ * null
if none
+ */
+ public void setProject(IJavaScriptProject project) {
+ this.project = project;
+ if (project != null) {
+ Map options = project.getOptions(true);
+ options.remove(JavaScriptCore.COMPILER_TASK_TAGS); // no need to parse task tags
+ this.compilerOptions = options;
+ }
+ }
+
+ /**
+ * Creates an abstract syntax tree.
+ *
+ * A successful call to this method returns all settings to their
+ * default values so the object is ready to be reused.
+ *
+ *
+ * @param monitor the progress monitor used to report progress and request cancelation,
+ * or null
if none
+ * @return an AST node whose type depends on the kind of parse
+ * requested, with a fallback to a JavaScriptUnit
+ * in the case of severe parsing errors
+ * @exception IllegalStateException if the settings provided
+ * are insufficient, contradictory, or otherwise unsupported
+ */
+ public ASTNode createAST(IProgressMonitor monitor) {
+ ASTNode result = null;
+ if (monitor != null) monitor.beginTask("", 1); //$NON-NLS-1$
+ try {
+ if (this.rawSource == null && this.typeRoot == null) {
+ throw new IllegalStateException("source not specified"); //$NON-NLS-1$
+ }
+ result = internalCreateAST(monitor);
+ } finally {
+ // re-init defaults to allow reuse (and avoid leaking)
+ initializeDefaults();
+ if (monitor != null) monitor.done();
+ }
+ return result;
+ }
+
+ /**
+ * Creates ASTs for a batch of javaScript units.
+ * When bindings are being resolved, processing a
+ * batch of javaScript units is more efficient because much
+ * of the work involved in resolving bindings can be shared.
+ *
+ * When bindings are being resolved, all javaScript units must
+ * come from the same JavaScript project, which must be set beforehand
+ * with setProject
.
+ * The javaScript units are processed one at a time in no
+ * specified order. For each of the javaScript units in turn,
+ *
+ * ASTParser.createAST
is called to parse it
+ * and create a corresponding AST. The calls to
+ * ASTParser.createAST
all employ the same settings.
+ * ASTRequestor.acceptAST
is called passing
+ * the javaScript unit and the corresponding AST to
+ * requestor
.
+ *
+ *
+ * Note only ASTs from the given javaScript units are reported
+ * to the requestor. If additional javaScript units are required to
+ * resolve the original ones, the corresponding ASTs are not
+ * reported to the requestor.
+ *
+ *
+ * Note also the following parser parameters are used, regardless of what
+ * may have been specified:
+ *
+ * - The {@linkplain #setKind(int) parser kind} is
K_JAVASCRIPT_UNIT
+ * - The {@linkplain #setSourceRange(int,int) source range} is
(0, -1)
+ * - The {@linkplain #setFocalPosition(int) focal position} is not set
+ *
+ *
+ *
+ * The bindingKeys
parameter specifies bindings keys
+ * ({@link IBinding#getKey()}) that are to be looked up. These keys may
+ * be for elements either inside or outside the set of compilation
+ * units being processed. When bindings are being resolved,
+ * the keys and corresponding bindings (or null
if none) are
+ * passed to ASTRequestor.acceptBinding
. Note that binding keys
+ * for elements outside the set of javaScript units being processed are looked up
+ * after all ASTRequestor.acceptAST
callbacks have been made.
+ * Binding keys for elements inside the set of javaScript units being processed
+ * are looked up and reported right after the corresponding
+ * ASTRequestor.acceptAST
callback has been made.
+ * No ASTRequestor.acceptBinding
callbacks are made unless
+ * bindings are being resolved.
+ *
+ *
+ * A successful call to this method returns all settings to their
+ * default values so the object is ready to be reused.
+ *
+ *
+ * @param compilationUnits the javaScript units to create ASTs for
+ * @param bindingKeys the binding keys to create bindings for
+ * @param requestor the AST requestor that collects abtract syntax trees and bindings
+ * @param monitor the progress monitor used to report progress and request cancelation,
+ * or null
if none
+ * @exception IllegalStateException if the settings provided
+ * are insufficient, contradictory, or otherwise unsupported
+ */
+ public void createASTs(IJavaScriptUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) {
+ try {
+ int flags = 0;
+ if (this.statementsRecovery) flags |= IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY;
+ if (this.resolveBindings) {
+ if (this.project == null)
+ throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+ if (this.bindingsRecovery) flags |= IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY;
+ JavaScriptUnitResolver.resolve(compilationUnits, bindingKeys, requestor, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
+ } else {
+ JavaScriptUnitResolver.parse(compilationUnits, requestor, this.apiLevel, this.compilerOptions, flags, monitor);
+ }
+ } finally {
+ // re-init defaults to allow reuse (and avoid leaking)
+ initializeDefaults();
+ }
+ }
+
+ /**
+ * Creates bindings for a batch of JavaScript elements. These elements are either
+ * enclosed in {@link IJavaScriptUnit}s or in {@link IClassFile}s.
+ *
+ * All enclosing javaScript units must
+ * come from the same JavaScript project, which must be set beforehand
+ * with setProject
.
+ *
+ *
+ * All elements must exist. If one doesn't exist, an IllegalStateException
+ * is thrown.
+ *
+ *
+ * The returned array has the same size as the given elements array. At a given position
+ * it contains the binding of the corresponding JavaScript element, or null
+ * if no binding could be created.
+ *
+ *
+ * Note also the following parser parameters are used, regardless of what
+ * may have been specified:
+ *
+ * - The {@linkplain #setResolveBindings(boolean) binding resolution flag} is
true
+ * - The {@linkplain #setKind(int) parser kind} is
K_JAVASCRIPT_UNIT
+ * - The {@linkplain #setSourceRange(int,int) source range} is
(0, -1)
+ * - The {@linkplain #setFocalPosition(int) focal position} is not set
+ *
+ *
+ *
+ * A successful call to this method returns all settings to their
+ * default values so the object is ready to be reused.
+ *
+ *
+ * @param elements the JavaScript elements to create bindings for
+ * @return the bindings for the given JavaScript elements, possibly containing null
s
+ * if some bindings could not be created
+ * @exception IllegalStateException if the settings provided
+ * are insufficient, contradictory, or otherwise unsupported
+ */
+ public IBinding[] createBindings(IJavaScriptElement[] elements, IProgressMonitor monitor) {
+ try {
+ if (this.project == null)
+ throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+ int flags = 0;
+ if (this.statementsRecovery) flags |= IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY;
+ if (this.bindingsRecovery) flags |= IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY;
+ return JavaScriptUnitResolver.resolve(elements, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner,flags, monitor);
+ } finally {
+ // re-init defaults to allow reuse (and avoid leaking)
+ initializeDefaults();
+ }
+ }
+
+ private ASTNode internalCreateAST(IProgressMonitor monitor) {
+ boolean needToResolveBindings = this.resolveBindings;
+ switch(this.astKind) {
+ case K_CLASS_BODY_DECLARATIONS :
+ case K_EXPRESSION :
+ case K_STATEMENTS :
+ if (this.rawSource != null) {
+ if (this.sourceOffset + this.sourceLength > this.rawSource.length) {
+ throw new IllegalStateException();
+ }
+ return internalCreateASTForKind();
+ }
+ break;
+ case K_COMPILATION_UNIT :
+ CompilationUnitDeclaration compilationUnitDeclaration = null;
+ try {
+ NodeSearcher searcher = null;
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
+ WorkingCopyOwner wcOwner = this.workingCopyOwner;
+ if (this.typeRoot instanceof IJavaScriptUnit) {
+ /*
+ * this.compilationUnitSource is an instance of org.eclipse.wst.jsdt.internal.core.CompilationUnit that implements
+ * both org.eclipse.wst.jsdt.core.IJavaScriptUnit and org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit
+ */
+ sourceUnit = (org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
+ /*
+ * use a BasicCompilation that caches the source instead of using the compilationUnitSource directly
+ * (if it is a working copy, the source can change between the parse and the AST convertion)
+ * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
+ */
+ sourceUnit = new BasicCompilationUnit(sourceUnit.getContents(), sourceUnit.getPackageName(), new String(sourceUnit.getFileName()), this.project);
+ wcOwner = ((IJavaScriptUnit) this.typeRoot).getOwner();
+ } else if (this.typeRoot instanceof IClassFile) {
+ try {
+ String sourceString = this.typeRoot.getSource();
+ if (sourceString == null) {
+ throw new IllegalStateException();
+ }
+ PackageFragment packageFragment = (PackageFragment) this.typeRoot.getParent();
+// BinaryType type = (BinaryType) this.typeRoot.findPrimaryType();
+ char[] fileName =this.typeRoot.getElementName().toCharArray();
+// IBinaryType binaryType = (IBinaryType) type.getElementInfo();
+// // file name is used to recreate the JavaScript element, so it has to be the toplevel .class file name
+// char[] fileName = type.getElementName().toCharArray();
+// int firstDollar = CharOperation.indexOf('$', fileName);
+// if (firstDollar != -1) {
+// char[] suffix = SuffixConstants.SUFFIX_class;
+// int suffixLength = suffix.length;
+// char[] newFileName = new char[firstDollar + suffixLength];
+// System.arraycopy(fileName, 0, newFileName, 0, firstDollar);
+// System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength);
+// fileName = newFileName;
+// }
+ sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), new String(fileName), this.project);
+ } catch(JavaScriptModelException e) {
+ // an error occured accessing the javaScript element
+ throw new IllegalStateException();
+ }
+ } else if (this.rawSource != null) {
+ needToResolveBindings = this.resolveBindings && this.unitName != null && this.project != null && this.compilerOptions != null;
+ sourceUnit = new BasicCompilationUnit(this.rawSource, null, this.unitName == null ? "" : this.unitName, this.project); //$NON-NLS-1$
+ } else {
+ throw new IllegalStateException();
+ }
+ if (this.partial) {
+ searcher = new NodeSearcher(this.focalPointPosition);
+ }
+ int flags = 0;
+ if (this.statementsRecovery) flags |= IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY;
+ if (needToResolveBindings) {
+ if (this.bindingsRecovery) flags |= IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY;
+ try {
+ // parse and resolve
+ compilationUnitDeclaration =
+ JavaScriptUnitResolver.resolve(
+ sourceUnit,
+ this.project,
+ searcher,
+ this.compilerOptions,
+ this.workingCopyOwner,
+ flags,
+ monitor);
+ } catch (JavaScriptModelException e) {
+ flags &= ~IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY;
+ compilationUnitDeclaration = JavaScriptUnitResolver.parse(
+ sourceUnit,
+ searcher,
+ this.compilerOptions,
+ flags);
+ needToResolveBindings = false;
+ }
+ } else {
+ compilationUnitDeclaration = JavaScriptUnitResolver.parse(
+ sourceUnit,
+ searcher,
+ this.compilerOptions,
+ flags);
+ needToResolveBindings = false;
+ }
+ JavaScriptUnit result = JavaScriptUnitResolver.convert(
+ compilationUnitDeclaration,
+ sourceUnit.getContents(),
+ this.apiLevel,
+ this.compilerOptions,
+ needToResolveBindings,
+ wcOwner,
+ needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null,
+ flags,
+ monitor);
+ result.setTypeRoot(this.typeRoot);
+ return result;
+ } finally {
+ if (compilationUnitDeclaration != null && this.resolveBindings) {
+ compilationUnitDeclaration.cleanUp();
+ if (compilationUnitDeclaration.scope!=null)
+ compilationUnitDeclaration.scope.cleanup();
+ }
+ }
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * Parses the given source between the bounds specified by the given offset (inclusive)
+ * and the given length and creates and returns a corresponding abstract syntax tree.
+ *
+ * When the parse is successful the result returned includes the ASTs for the
+ * requested source:
+ *
+ * - {@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
+ * is a {@link TypeDeclaration TypeDeclaration} whose
+ * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
+ * are the new trees. Other aspects of the type declaration are unspecified.
+ * - {@link #K_STATEMENTS K_STATEMENTS}: The result node is a
+ * {@link Block Block} whose {@link Block#statements() statements}
+ * are the new trees. Other aspects of the block are unspecified.
+ * - {@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
+ * {@link Expression Expression}. Other aspects of the expression are unspecified.
+ *
+ * The resulting AST node is rooted under an contrived
+ * {@link JavaScriptUnit JavaScriptUnit} node, to allow the
+ * client to retrieve the following pieces of information
+ * available there:
+ *
+ * - {@linkplain JavaScriptUnit#getLineNumber(int) Line number map}. Line
+ * numbers start at 1 and only cover the subrange scanned
+ * (
source[offset]
through source[offset+length-1]
).
+ * - {@linkplain JavaScriptUnit#getMessages() Compiler messages}
+ * and {@linkplain JavaScriptUnit#getProblems() detailed problem reports}.
+ * Character positions are relative to the start of
+ *
source
; line positions are for the subrange scanned.
+ * - {@linkplain JavaScriptUnit#getCommentList() Comment list}
+ * for the subrange scanned.
+ *
+ * The contrived nodes do not have source positions. Other aspects of the
+ * {@link JavaScriptUnit JavaScriptUnit} node are unspecified, including
+ * the exact arrangment of intervening nodes.
+ *
+ *
+ * Lexical or syntax errors detected while parsing can result in
+ * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
+ * In more severe failure cases where the parser is unable to
+ * recognize the input, this method returns
+ * a {@link JavaScriptUnit JavaScriptUnit} node with at least the
+ * validator messages.
+ *
+ * Each node in the subtree (other than the contrived nodes)
+ * carries source range(s) information relating back
+ * to positions in the given source (the given source itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ *
+ *
+ * This method does not compute binding information; all resolveBinding
+ * methods applied to nodes of the resulting AST return null
.
+ *
+ *
+ * @return an AST node whose type depends on the kind of parse
+ * requested, with a fallback to a JavaScriptUnit
+ * in the case of severe parsing errors
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ */
+ private ASTNode internalCreateASTForKind() {
+ final ASTConverter converter = new ASTConverter(this.compilerOptions, false, null);
+ converter.compilationUnitSource = this.rawSource;
+ converter.compilationUnitSourceLength = this.rawSource.length;
+ converter.scanner.setSource(this.rawSource);
+
+ AST ast = AST.newAST(this.apiLevel);
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ ast.setBindingResolver(new BindingResolver());
+ if (this.statementsRecovery) {
+ ast.setFlag(IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY);
+ }
+ converter.setAST(ast);
+ CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
+ JavaScriptUnit compilationUnit = ast.newJavaScriptUnit();
+ if (this.sourceLength == -1) {
+ this.sourceLength = this.rawSource.length;
+ }
+ switch(this.astKind) {
+ case K_STATEMENTS :
+ ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, this.statementsRecovery);
+ RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData;
+ if(data != null) {
+ Scanner scanner = converter.scanner;
+ converter.scanner = new RecoveryScanner(scanner, data.removeUnused());
+ converter.docParser.scanner = converter.scanner;
+ converter.scanner.setSource(scanner.source);
+ }
+ RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+ int[][] comments = recordedParsingInformation.commentPositions;
+ if (comments != null) {
+ converter.buildCommentsTable(compilationUnit, comments);
+ }
+ compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+ Block block = ast.newBlock();
+ block.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
+ org.eclipse.wst.jsdt.internal.compiler.ast.Statement[] statements = constructorDeclaration.statements;
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ if (statements[i] instanceof org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration) {
+ converter.checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+ } else {
+ Statement statement = converter.convert(statements[i]);
+ if (statement != null) {
+ block.statements().add(statement);
+ }
+ }
+ }
+ }
+ rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation, data);
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return block;
+ case K_EXPRESSION :
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil.parseExpression(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
+ recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+ comments = recordedParsingInformation.commentPositions;
+ if (comments != null) {
+ converter.buildCommentsTable(compilationUnit, comments);
+ }
+ compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+ if (expression != null) {
+ Expression expression2 = converter.convert(expression);
+ rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation, null);
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return expression2;
+ } else {
+ CategorizedProblem[] problems = recordedParsingInformation.problems;
+ if (problems != null) {
+ compilationUnit.setProblems(problems);
+ }
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ }
+ case K_CLASS_BODY_DECLARATIONS :
+ final org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil.parseClassBodyDeclarations(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
+ recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+ comments = recordedParsingInformation.commentPositions;
+ if (comments != null) {
+ converter.buildCommentsTable(compilationUnit, comments);
+ }
+ compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+ if (nodes != null) {
+// TypeDeclaration typeDeclaration = converter.convert(nodes);
+// typeDeclaration.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
+// rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation, null);
+ JavaScriptUnit compUnit=converter.convert(nodes, compilationUnit);
+ rootNodeToCompilationUnit(compUnit.getAST(), compilationUnit, compUnit, codeSnippetParsingUtil.recordedParsingInformation, null);
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ } else {
+ CategorizedProblem[] problems = recordedParsingInformation.problems;
+ if (problems != null) {
+ compilationUnit.setProblems(problems);
+ }
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ }
+ }
+ throw new IllegalStateException();
+ }
+
+ private void propagateErrors(ASTNode astNode, CategorizedProblem[] problems, RecoveryScannerData data) {
+ astNode.accept(new ASTSyntaxErrorPropagator(problems));
+ if (data != null) {
+ astNode.accept(new ASTRecoveryPropagator(problems, data));
+ }
+ }
+
+ private void rootNodeToCompilationUnit(AST ast, JavaScriptUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation, RecoveryScannerData data) {
+ final int problemsCount = recordedParsingInformation.problemsCount;
+ switch(node.getNodeType()) {
+ case ASTNode.BLOCK :
+ {
+ Block block = (Block) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ propagateErrors(block, problems, data);
+ compilationUnit.setProblems(problems);
+ }
+ TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
+ Initializer initializer = ast.newInitializer();
+ initializer.setBody(block);
+ typeDeclaration.bodyDeclarations().add(initializer);
+ compilationUnit.types().add(typeDeclaration);
+ }
+ break;
+ case ASTNode.JAVASCRIPT_UNIT :
+ {
+ JavaScriptUnit compUnit = (JavaScriptUnit) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ for (int i = 0, max = compUnit.statements().size(); i < max; i++) {
+ propagateErrors((ASTNode) compUnit.statements().get(i), problems, data);
+ }
+ compilationUnit.setProblems(problems);
+ }
+ if (compilationUnit!=node)
+ for (int i = 0, max = compUnit.statements().size(); i < max; i++)
+ compilationUnit.statements().add(compUnit.statements().get(i));
+ }
+ break;
+ case ASTNode.TYPE_DECLARATION :
+ {
+ TypeDeclaration typeDeclaration = (TypeDeclaration) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ propagateErrors(typeDeclaration, problems, data);
+ compilationUnit.setProblems(problems);
+ }
+ compilationUnit.types().add(typeDeclaration);
+ }
+ break;
+ default :
+ if (node instanceof Expression) {
+ Expression expression = (Expression) node;
+ if (problemsCount != 0) {
+ // propagate and record problems
+ final CategorizedProblem[] problems = recordedParsingInformation.problems;
+ propagateErrors(expression, problems, data);
+ compilationUnit.setProblems(problems);
+ }
+ ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
+ Block block = ast.newBlock();
+ block.statements().add(expressionStatement);
+ Initializer initializer = ast.newInitializer();
+ initializer.setBody(block);
+ TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
+ typeDeclaration.bodyDeclarations().add(initializer);
+ compilationUnit.types().add(typeDeclaration);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTRecoveryPropagator.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTRecoveryPropagator.java
new file mode 100644
index 0000000..9853413
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTRecoveryPropagator.java
@@ -0,0 +1,382 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObjectToIntArray;
+
+/**
+ * Internal AST visitor for propagating syntax errors.
+ */
+class ASTRecoveryPropagator extends DefaultASTVisitor {
+ private static final int NOTHING = -1;
+ HashtableOfObjectToIntArray endingTokens = new HashtableOfObjectToIntArray();
+ {
+ this.endingTokens.put(AnonymousClassDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(ArrayAccess.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(ArrayCreation.class, new int[]{NOTHING, TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(ArrayInitializer.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(ArrayType.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+ this.endingTokens.put(Block.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(BooleanLiteral.class, new int[]{TerminalTokens.TokenNamefalse, TerminalTokens.TokenNametrue});
+ this.endingTokens.put(BreakStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(CharacterLiteral.class, new int[]{TerminalTokens.TokenNameCharacterLiteral});
+ this.endingTokens.put(RegularExpressionLiteral.class, new int[]{TerminalTokens.TokenNameRegExLiteral});
+ this.endingTokens.put(ClassInstanceCreation.class, new int[]{TerminalTokens.TokenNameRBRACE, TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(ConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ContinueStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(DoStatement.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(EmptyStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ExpressionStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(FieldDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ImportDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(Initializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(FunctionDeclaration.class, new int[]{NOTHING, TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(FunctionInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(NullLiteral.class, new int[]{TerminalTokens.TokenNamenull});
+ this.endingTokens.put(UndefinedLiteral.class, new int[]{TerminalTokens.TokenNameundefined});
+ this.endingTokens.put(NumberLiteral.class, new int[]{TerminalTokens.TokenNameIntegerLiteral, TerminalTokens.TokenNameLongLiteral, TerminalTokens.TokenNameFloatingPointLiteral, TerminalTokens.TokenNameDoubleLiteral});
+ this.endingTokens.put(PackageDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(ParenthesizedExpression.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(PostfixExpression.class, new int[]{TerminalTokens.TokenNamePLUS_PLUS, TerminalTokens.TokenNameMINUS_MINUS});
+ this.endingTokens.put(PrimitiveType.class, new int[]{TerminalTokens.TokenNamebyte, TerminalTokens.TokenNameshort, TerminalTokens.TokenNamechar, TerminalTokens.TokenNameint, TerminalTokens.TokenNamelong, TerminalTokens.TokenNamefloat, TerminalTokens.TokenNameboolean, TerminalTokens.TokenNamedouble, TerminalTokens.TokenNamevoid});
+ this.endingTokens.put(ReturnStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(SimpleName.class, new int[]{TerminalTokens.TokenNameIdentifier});
+ this.endingTokens.put(SingleVariableDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(StringLiteral.class, new int[]{TerminalTokens.TokenNameStringLiteral});
+ this.endingTokens.put(SuperConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(SuperMethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+ this.endingTokens.put(SwitchCase.class, new int[]{TerminalTokens.TokenNameCOLON});
+ this.endingTokens.put(SwitchStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(ThisExpression.class, new int[]{TerminalTokens.TokenNamethis});
+ this.endingTokens.put(ThrowStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ this.endingTokens.put(TypeDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+ this.endingTokens.put(TypeLiteral.class, new int[]{TerminalTokens.TokenNameclass});
+ this.endingTokens.put(VariableDeclarationStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+ }
+
+ private CategorizedProblem[] problems;
+ private boolean[] usedOrIrrelevantProblems;
+
+ private RecoveryScannerData data;
+ private int blockDepth = 0;
+ private int lastEnd;
+
+ private int[] insertedTokensKind;
+ private int[] insertedTokensPosition;
+ private boolean[] insertedTokensFlagged;
+
+ private boolean[] removedTokensFlagged;
+ private boolean[] replacedTokensFlagged;
+
+ private Vector stack = new Vector();
+
+ ASTRecoveryPropagator(CategorizedProblem[] problems, RecoveryScannerData data) {
+ // visit Javadoc.tags() as well
+ this.problems = problems;
+ this.usedOrIrrelevantProblems = new boolean[problems.length];
+
+ this.data = data;
+
+ if(this.data != null) {
+
+ int length = 0;
+ for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
+ length += data.insertedTokens[i].length;
+ }
+ this.insertedTokensKind = new int[length];
+ this.insertedTokensPosition = new int[length];
+ this.insertedTokensFlagged = new boolean[length];
+ int tokenCount = 0;
+ for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
+ for (int j = 0; j < data.insertedTokens[i].length; j++) {
+ this.insertedTokensKind[tokenCount] = data.insertedTokens[i][j];
+ this.insertedTokensPosition[tokenCount] = data.insertedTokensPosition[i];
+ tokenCount++;
+ }
+ }
+
+ if(data.removedTokensPtr != -1) {
+ this.removedTokensFlagged = new boolean[data.removedTokensPtr + 1];
+ }
+ if(data.replacedTokensPtr != -1) {
+ this.replacedTokensFlagged = new boolean[data.replacedTokensPtr + 1];
+ }
+ }
+ }
+
+ public void endVisit(Block node) {
+ this.blockDepth--;
+ if(this.blockDepth <= 0) {
+ flagNodeWithInsertedTokens();
+ }
+ super.endVisit(node);
+ }
+
+
+
+ public boolean visit(Block node) {
+ boolean visitChildren = super.visit(node);
+ this.blockDepth++;
+ return visitChildren;
+ }
+
+ protected boolean visitNode(ASTNode node) {
+ if(this.blockDepth > 0) {
+ if (node instanceof InferredType)
+ return true;
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+
+ // continue to visit the node only if it contains tokens modifications
+
+ if(this.insertedTokensFlagged != null) {
+ for (int i = 0; i < this.insertedTokensFlagged.length; i++) {
+ if(this.insertedTokensPosition[i] >= start &&
+ this.insertedTokensPosition[i] <= end) {
+ return true;
+ }
+ }
+ }
+
+ if(this.removedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.removedTokensPtr; i++) {
+ if(this.data.removedTokensStart[i] >= start &&
+ this.data.removedTokensEnd[i] <= end) {
+ return true;
+ }
+ }
+ }
+
+ if(this.replacedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
+ if(this.data.replacedTokensStart[i] >= start &&
+ this.data.replacedTokensEnd[i] <= end) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ return true;
+ }
+
+ protected void endVisitNode(ASTNode node) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+
+ // is inside diet part of the ast
+ if(this.blockDepth < 1) {
+ if(this.markIncludedProblems(start, end)) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ }
+ } else {
+ this.markIncludedProblems(start, end);
+
+ if(this.insertedTokensFlagged != null) {
+ if(this.lastEnd != end) {
+ flagNodeWithInsertedTokens();
+ }
+ this.stack.add(node);
+ }
+
+ if(this.removedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.removedTokensPtr; i++) {
+ if(!this.removedTokensFlagged[i] &&
+ this.data.removedTokensStart[i] >= start &&
+ this.data.removedTokensEnd[i] <= end) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ this.removedTokensFlagged[i] = true;
+ }
+ }
+ }
+
+ if(this.replacedTokensFlagged != null) {
+ for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
+ if(!this.replacedTokensFlagged[i] &&
+ this.data.replacedTokensStart[i] >= start &&
+ this.data.replacedTokensEnd[i] <= end) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ this.replacedTokensFlagged[i] = true;
+ }
+ }
+ }
+ }
+ this.lastEnd = end;
+ }
+
+ private void flagNodeWithInsertedTokens() {
+ if(this.insertedTokensKind != null && this.insertedTokensKind.length > 0) {
+ int s = this.stack.size();
+ for (int i = s - 1; i > -1; i--) {
+ flagNodesWithInsertedTokensAtEnd((ASTNode)this.stack.get(i));
+ }
+ for (int i = 0; i < s; i++) {
+ flagNodesWithInsertedTokensInside((ASTNode)this.stack.get(i));
+ }
+ this.stack = new Vector();
+ }
+ }
+
+ private boolean flagNodesWithInsertedTokensAtEnd(ASTNode node) {
+ int[] expectedEndingToken = this.endingTokens.get(node.getClass());
+ if (expectedEndingToken != null) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+
+ boolean flagParent = false;
+ done : for (int i = this.insertedTokensKind.length - 1; i > -1 ; i--) {
+ if(!this.insertedTokensFlagged[i] &&
+ this.insertedTokensPosition[i] == end){
+ this.insertedTokensFlagged[i] = true;
+ for (int j = 0; j < expectedEndingToken.length; j++) {
+ if(expectedEndingToken[j] == this.insertedTokensKind[i]) {
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ break done;
+ }
+ }
+ flagParent = true;
+ }
+ }
+
+ if(flagParent) {
+ ASTNode parent = node.getParent();
+ while (parent != null) {
+ parent.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ if((parent.getStartPosition() + parent.getLength() - 1) != end) {
+ parent = null;
+ } else {
+ parent = parent.getParent();
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean flagNodesWithInsertedTokensInside(ASTNode node) {
+ int start = node.getStartPosition();
+ int end = start + node.getLength() - 1;
+ for (int i = 0; i < this.insertedTokensKind.length; i++) {
+ if(!this.insertedTokensFlagged[i] &&
+ start <= this.insertedTokensPosition[i] &&
+ this.insertedTokensPosition[i] < end){
+ node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+ this.insertedTokensFlagged[i] = true;
+ }
+ }
+ return true;
+ }
+
+ private boolean markIncludedProblems(int start, int end) {
+ boolean foundProblems = false;
+ next: for (int i = 0, max = this.problems.length; i < max; i++) {
+ CategorizedProblem problem = this.problems[i];
+
+ if(this.usedOrIrrelevantProblems[i]) continue next;
+
+ switch(problem.getID()) {
+ case IProblem.ParsingErrorOnKeywordNoSuggestion :
+ case IProblem.ParsingErrorOnKeyword :
+ case IProblem.ParsingError :
+ case IProblem.ParsingErrorNoSuggestion :
+ case IProblem.ParsingErrorInsertTokenBefore :
+ case IProblem.ParsingErrorInsertTokenAfter :
+ case IProblem.ParsingErrorDeleteToken :
+ case IProblem.ParsingErrorDeleteTokens :
+ case IProblem.ParsingErrorMergeTokens :
+ case IProblem.ParsingErrorInvalidToken :
+ case IProblem.ParsingErrorMisplacedConstruct :
+ case IProblem.ParsingErrorReplaceTokens :
+ case IProblem.ParsingErrorNoSuggestionForTokens :
+ case IProblem.ParsingErrorUnexpectedEOF :
+ case IProblem.ParsingErrorInsertToComplete :
+ case IProblem.ParsingErrorInsertToCompleteScope :
+ case IProblem.ParsingErrorInsertToCompletePhrase :
+ case IProblem.EndOfSource :
+ case IProblem.InvalidHexa :
+ case IProblem.InvalidOctal :
+ case IProblem.InvalidCharacterConstant :
+ case IProblem.InvalidEscape :
+ case IProblem.InvalidInput :
+ case IProblem.InvalidUnicodeEscape :
+ case IProblem.InvalidFloat :
+ case IProblem.NullSourceString :
+ case IProblem.UnterminatedString :
+ case IProblem.UnterminatedComment :
+ case IProblem.InvalidDigit :
+ break;
+ default:
+ this.usedOrIrrelevantProblems[i] = true;
+ continue next;
+
+ }
+
+ int problemStart = problem.getSourceStart();
+ int problemEnd = problem.getSourceEnd();
+ if ((start <= problemStart) && (problemStart <= end) ||
+ (start <= problemEnd) && (problemEnd <= end)) {
+ this.usedOrIrrelevantProblems[i] = true;
+ foundProblems = true;
+ }
+ }
+ return foundProblems;
+ }
+
+ public void endVisit(ExpressionStatement node) {
+ endVisitNode(node);
+ if ((node.getFlags() & ASTNode.RECOVERED) == 0) return;
+ Expression expression = node.getExpression();
+ if (expression.getNodeType() == ASTNode.ASSIGNMENT) {
+ Assignment assignment = (Assignment) expression;
+ Expression rightHandSide = assignment.getRightHandSide();
+ if (rightHandSide.getNodeType() == ASTNode.SIMPLE_NAME) {
+ SimpleName simpleName = (SimpleName) rightHandSide;
+ if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+ Expression expression2 = assignment.getLeftHandSide();
+ // unparent the expression to add it in the expression stateemnt
+ expression2.setParent(null, null);
+ expression2.setFlags(expression2.getFlags() | ASTNode.RECOVERED);
+ node.setExpression(expression2);
+ }
+ }
+ }
+ }
+
+ public void endVisit(VariableDeclarationStatement node) {
+ endVisitNode(node);
+ List fragments = node.fragments();
+ for (int i = 0, max = fragments.size(); i ASTParser.createASTs
.
+ *
+ * ASTRequestor.acceptAST
is called for each of the
+ * javaScript units passed to ASTParser.createASTs
.
+ * After all the javaScript units have been processed,
+ * ASTRequestor.acceptBindings
is called for each
+ * of the binding keys passed to ASTParser.createASTs
.
+ *
+ *
+ * This class is intended to be subclassed by clients.
+ * AST requestors are serially reusable, but neither reentrant nor
+ * thread-safe.
+ *
+ *
+ * @see ASTParser#createASTs(IJavaScriptUnit[], String[], ASTRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class ASTRequestor {
+
+ /**
+ * The javaScript unit resolver used to resolve bindings, or
+ * null
if none. Note that this field is non-null
+ * only within the dynamic scope of a call to
+ * ASTParser.createASTs
.
+ */
+ JavaScriptUnitResolver compilationUnitResolver = null;
+
+ /**
+ * Creates a new instance.
+ */
+ protected ASTRequestor() {
+ // do nothing
+ }
+
+ /**
+ * Accepts an AST corresponding to the javaScript unit.
+ * That is, ast
is an AST for source
.
+ *
+ * The default implementation of this method does nothing.
+ * Clients should override to process the resulting AST.
+ *
+ *
+ * @param source the javaScript unit the ast is coming from
+ * @param ast the requested abtract syntax tree
+ */
+ public void acceptAST(IJavaScriptUnit source, JavaScriptUnit ast) {
+ // do nothing
+ }
+
+ /**
+ * Accepts a binding corresponding to the binding key.
+ * That is, binding
is the binding for
+ * bindingKey
; binding
is null
+ * if the key cannot be resolved.
+ *
+ * The default implementation of this method does nothing.
+ * Clients should override to process the resulting binding.
+ *
+ *
+ * @param bindingKey the key of the requested binding
+ * @param binding the requested binding, or null
if none
+ */
+ public void acceptBinding(String bindingKey, IBinding binding) {
+ // do nothing
+ }
+
+ /**
+ * Resolves bindings for the given binding keys.
+ * The given binding keys must have been obtained earlier
+ * using {@link IBinding#getKey()}.
+ *
+ * If a binding key cannot be resolved, null
is put in the resulting array.
+ * Bindings can only be resolved in the dynamic scope of a ASTParser.createASTs
,
+ * and only if ASTParser.resolveBindings(true)
was specified.
+ *
+ *
+ * Caveat: During an acceptAST
callback, there are implementation
+ * limitations concerning the look up of binding keys representing local elements.
+ * In some cases, the binding is unavailable, and null
will be returned.
+ * This is only an issue during an acceptAST
callback, and only
+ * when the binding key represents a local element (e.g., local variable,
+ * local class, method declared in anonymous class). There is no such limitation
+ * outside of acceptAST
callbacks, or for top-level types and their
+ * members even within acceptAST
callbacks.
+ *
+ *
+ * @param bindingKeys the binding keys to look up
+ * @return a list of bindings paralleling the bindingKeys
parameter,
+ * with null
entries for keys that could not be resolved
+ */
+ public final IBinding[] createBindings(String[] bindingKeys) {
+ int length = bindingKeys.length;
+ IBinding[] result = new IBinding[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = null;
+ if (this.compilationUnitResolver != null) {
+ result[i] = this.compilationUnitResolver.createBinding(bindingKeys[i]);
+ }
+ }
+ return result;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTSyntaxErrorPropagator.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTSyntaxErrorPropagator.java
new file mode 100644
index 0000000..9ed9163
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTSyntaxErrorPropagator.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+
+/**
+ * Internal AST visitor for propagating syntax errors.
+ */
+class ASTSyntaxErrorPropagator extends ASTVisitor {
+
+ private CategorizedProblem[] problems;
+
+ ASTSyntaxErrorPropagator(CategorizedProblem[] problems) {
+ // visit Javadoc.tags() as well
+ super(true);
+ this.problems = problems;
+ }
+
+ private boolean checkAndTagAsMalformed(ASTNode node) {
+ boolean tagWithErrors = false;
+ search: for (int i = 0, max = this.problems.length; i < max; i++) {
+ CategorizedProblem problem = this.problems[i];
+ switch(problem.getID()) {
+ case IProblem.ParsingErrorOnKeywordNoSuggestion :
+ case IProblem.ParsingErrorOnKeyword :
+ case IProblem.ParsingError :
+ case IProblem.ParsingErrorNoSuggestion :
+ case IProblem.ParsingErrorInsertTokenBefore :
+ case IProblem.ParsingErrorInsertTokenAfter :
+ case IProblem.ParsingErrorDeleteToken :
+ case IProblem.ParsingErrorDeleteTokens :
+ case IProblem.ParsingErrorMergeTokens :
+ case IProblem.ParsingErrorInvalidToken :
+ case IProblem.ParsingErrorMisplacedConstruct :
+ case IProblem.ParsingErrorReplaceTokens :
+ case IProblem.ParsingErrorNoSuggestionForTokens :
+ case IProblem.ParsingErrorUnexpectedEOF :
+ case IProblem.ParsingErrorInsertToComplete :
+ case IProblem.ParsingErrorInsertToCompleteScope :
+ case IProblem.ParsingErrorInsertToCompletePhrase :
+ case IProblem.EndOfSource :
+ case IProblem.InvalidHexa :
+ case IProblem.InvalidOctal :
+ case IProblem.InvalidCharacterConstant :
+ case IProblem.InvalidEscape :
+ case IProblem.InvalidInput :
+ case IProblem.InvalidUnicodeEscape :
+ case IProblem.InvalidFloat :
+ case IProblem.NullSourceString :
+ case IProblem.UnterminatedString :
+ case IProblem.UnterminatedComment :
+ case IProblem.InvalidDigit :
+ break;
+ default:
+ continue search;
+ }
+ int position = problem.getSourceStart();
+ int start = node.getStartPosition();
+ int end = start + node.getLength();
+ if ((start <= position) && (position <= end)) {
+ node.setFlags(node.getFlags() | ASTNode.MALFORMED);
+ // clear the bits on parent
+ ASTNode currentNode = node.getParent();
+ while (currentNode != null) {
+ currentNode.setFlags(currentNode.getFlags() & ~ASTNode.MALFORMED);
+ currentNode = currentNode.getParent();
+ }
+ tagWithErrors = true;
+ }
+ }
+ return tagWithErrors;
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(FieldDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(FunctionDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(PackageDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(ImportDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(JavaScriptUnit node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(TypeDeclaration node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+ /*
+ * Method declared on ASTVisitor.
+ */
+ public boolean visit(Initializer node) {
+ return checkAndTagAsMalformed(node);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTVisitor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTVisitor.java
new file mode 100644
index 0000000..6ee1df0
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ASTVisitor.java
@@ -0,0 +1,2212 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * A visitor for abstract syntax trees.
+ *
+ * For each different concrete AST node type T there are
+ * a pair of methods:
+ *
+ * public boolean visit(T node)
- Visits
+ * the given node to perform some arbitrary operation. If true
+ * is returned, the given node's child nodes will be visited next; however,
+ * if false
is returned, the given node's child nodes will
+ * not be visited. The default implementation provided by this class does
+ * nothing and returns true
(with the exception of
+ * {@link #visit(JSdoc) ASTVisitor.visit(Javadoc)}).
+ * Subclasses may reimplement this method as needed.
+ * public void endVisit(T node)
- Visits
+ * the given node to perform some arbitrary operation. When used in the
+ * conventional way, this method is called after all of the given node's
+ * children have been visited (or immediately, if visit
returned
+ * false
). The default implementation provided by this class does
+ * nothing. Subclasses may reimplement this method as needed.
+ *
+ *
+ * In addition, there are a pair of methods for visiting AST nodes in the
+ * abstract, regardless of node type:
+ *
+ * public void preVisit(ASTNode node)
- Visits
+ * the given node to perform some arbitrary operation.
+ * This method is invoked prior to the appropriate type-specific
+ * visit
method.
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement this method as needed.
+ * public void postVisit(ASTNode node)
- Visits
+ * the given node to perform some arbitrary operation.
+ * This method is invoked after the appropriate type-specific
+ * endVisit
method.
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement this method as needed.
+ *
+ *
+ * For nodes with list-valued properties, the child nodes within the list
+ * are visited in order. For nodes with multiple properties, the child nodes
+ * are visited in the order that most closely corresponds to the lexical
+ * reading order of the source program. For instance, for a type declaration
+ * node, the child ordering is: name, superclass, superinterfaces, and
+ * body declarations.
+ *
+ *
+ * While it is possible to modify the tree in the visitor, care is required to
+ * ensure that the consequences are as expected and desirable.
+ * During the course of an ordinary visit starting at a given node, every node
+ * in the subtree is visited exactly twice, first with visit
and
+ * then with endVisit
. During a traversal of a stationary tree,
+ * each node is either behind (after endVisit
), ahead (before
+ * visit
), or in progress (between visit
and
+ * the matching endVisit
). Changes to the "behind" region of the
+ * tree are of no consequence to the visit in progress. Changes to the "ahead"
+ * region will be taken in stride. Changes to the "in progress" portion are
+ * the more interesting cases. With a node, the various properties are arranged
+ * in a linear list, with a cursor that separates the properties that have
+ * been visited from the ones that are still to be visited (the cursor
+ * is between the elements, rather than on an element). The cursor moves from
+ * the head to the tail of this list, advancing to the next position just
+ * before visit
if called for that child. After the child
+ * subtree has been completely visited, the visit moves on the child
+ * immediately after the cursor. Removing a child while it is being visited
+ * does not alter the course of the visit. But any children added at positions
+ * after the cursor are considered in the "ahead" portion and will be visited.
+ *
+ *
+ * Cases to watch out for:
+ *
+ * - Moving a child node further down the list. This could result in the
+ * child subtree being visited multiple times; these visits are sequential.
+ * - Moving a child node up into an ancestor. If the new home for
+ * the node is in the "ahead" portion, the subtree will be visited
+ * a second time; again, these visits are sequential.
+ * - Moving a node down into a child. If the new home for
+ * the node is in the "ahead" portion, the subtree will be visited
+ * a second time; in this case, the visits will be nested. In some cases,
+ * this can lead to a stack overflow or out of memory condition.
+ *
+ * Note that {@link LineComment} and {@link BlockComment} nodes are
+ * not normally visited in an AST because they are not considered
+ * part of main structure of the AST. Use
+ * {@link JavaScriptUnit#getCommentList()} to find these additional
+ * comments nodes.
+ *
+ *
+ * @see org.eclipse.wst.jsdt.core.dom.ASTNode#accept(ASTVisitor)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class ASTVisitor {
+
+ /**
+ * Indicates whether doc tags should be visited by default.
+ */
+ private boolean visitDocTags;
+
+ /**
+ * Creates a new AST visitor instance.
+ *
+ * For backwards compatibility, the visitor does not visit tag
+ * elements below doc comments by default. Use
+ * {@link #ASTVisitor(boolean) ASTVisitor(true)}
+ * for an visitor that includes doc comments by default.
+ *
+ */
+ public ASTVisitor() {
+ this(false);
+ }
+
+ /**
+ * Creates a new AST visitor instance.
+ *
+ * @param visitDocTags true
if doc comment tags are
+ * to be visited by default, and false
otherwise
+ * @see JSdoc#tags()
+ * @see #visit(JSdoc)
+ */
+ public ASTVisitor(boolean visitDocTags) {
+ this.visitDocTags = visitDocTags;
+ }
+
+ /**
+ * Visits the given AST node prior to the type-specific visit.
+ * (before visit
).
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void preVisit(ASTNode node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Visits the given AST node following the type-specific visit
+ * (after endVisit
).
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void postVisit(ASTNode node) {
+ // default implementation: do nothing
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(AnonymousClassDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayAccess node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayCreation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayInitializer node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ArrayType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Assignment node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Block node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ * Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BlockComment node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BooleanLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(BreakStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CatchClause node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(CharacterLiteral node) {
+ return true;
+ }
+
+ public boolean visit(RegularExpressionLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ClassInstanceCreation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(JavaScriptUnit node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ConditionalExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ConstructorInvocation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ContinueStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(DoStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(EmptyStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(EnhancedForStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ExpressionStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FieldAccess node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FieldDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ForStatement node) {
+ return true;
+ }
+
+ public boolean visit(ForInStatement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(IfStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ImportDeclaration node) {
+ return true;
+ }
+
+
+ public boolean visit(InferredType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(InfixExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(InstanceofExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Initializer node) {
+ return true;
+ }
+
+ /**
+ * Visits the given AST node.
+ *
+ * Unlike other node types, the boolean returned by the default
+ * implementation is controlled by a constructor-supplied
+ * parameter {@link #ASTVisitor(boolean) ASTVisitor(boolean)}
+ * which is false
by default.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ * @see #ASTVisitor()
+ * @see #ASTVisitor(boolean)
+ */
+ public boolean visit(JSdoc node) {
+ // visit tag elements inside doc comments only if requested
+ return this.visitDocTags;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(LabeledStatement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ * Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(LineComment node) {
+ return true;
+ }
+
+
+ public boolean visit(ListExpression node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(MemberRef node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FunctionRef node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FunctionRefParameter node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FunctionDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(FunctionInvocation node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(Modifier node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(NullLiteral node) {
+ return true;
+ }
+
+ public boolean visit(UndefinedLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(NumberLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PackageDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ParenthesizedExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PostfixExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PrefixExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(PrimitiveType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(QualifiedName node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(QualifiedType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ReturnStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SimpleName node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SimpleType node) {
+ return true;
+ }
+
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SingleVariableDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(StringLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SuperConstructorInvocation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SuperFieldAccess node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SuperMethodInvocation node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SwitchCase node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(SwitchStatement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TagElement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TextElement node) {
+ return true;
+ }
+
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ThisExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(ThrowStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TryStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeDeclaration node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeDeclarationStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(TypeLiteral node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(VariableDeclarationExpression node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(VariableDeclarationStatement node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(VariableDeclarationFragment node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ *
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ * @return true
if the children of this node should be
+ * visited, and false
if the children of this node should
+ * be skipped
+ */
+ public boolean visit(WhileStatement node) {
+ return true;
+ }
+
+ public boolean visit(WithStatement node) {
+ return true;
+ }
+
+ public boolean visit(ObjectLiteral node) {
+ return true;
+ }
+ public boolean visit(ObjectLiteralField node) {
+ return true;
+ }
+ public boolean visit(FunctionExpression node) {
+ return true;
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(AnonymousClassDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayAccess node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayCreation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayInitializer node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ArrayType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Assignment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Block node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ * Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BlockComment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BooleanLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(BreakStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CatchClause node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(CharacterLiteral node) {
+ // default implementation: do nothing
+ }
+ public void endVisit(RegularExpressionLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ClassInstanceCreation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(JavaScriptUnit node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ConditionalExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ConstructorInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ContinueStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(DoStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(EmptyStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(EnhancedForStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ExpressionStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FieldAccess node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FieldDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ForStatement node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(ForInStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(IfStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ImportDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(InfixExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(InstanceofExpression node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(InferredType node) {
+ // default implementation: do nothing
+ }
+
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Initializer node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(JSdoc node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(LabeledStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ * Note: {@link LineComment} and {@link BlockComment} nodes are
+ * not considered part of main structure of the AST. This method will
+ * only be called if a client goes out of their way to visit this
+ * kind of node explicitly.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(LineComment node) {
+ // default implementation: do nothing
+ }
+
+
+ public void endVisit(ListExpression node) {
+ // default implementation: do nothing
+ }
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(MemberRef node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FunctionRef node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FunctionRefParameter node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FunctionDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(FunctionInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(Modifier node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(NullLiteral node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(UndefinedLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(NumberLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PackageDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ParenthesizedExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PostfixExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PrefixExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(PrimitiveType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(QualifiedName node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(QualifiedType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ReturnStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SimpleName node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SimpleType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SingleVariableDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(StringLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SuperConstructorInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SuperFieldAccess node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SuperMethodInvocation node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SwitchCase node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(SwitchStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TagElement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TextElement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ThisExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(ThrowStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TryStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeDeclaration node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeDeclarationStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(TypeLiteral node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(VariableDeclarationExpression node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(VariableDeclarationStatement node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(VariableDeclarationFragment node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ *
+ * The default implementation does nothing. Subclasses may reimplement.
+ *
+ *
+ * @param node the node to visit
+ */
+ public void endVisit(WhileStatement node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(WithStatement node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(ObjectLiteral node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(ObjectLiteralField node) {
+ // default implementation: do nothing
+ }
+
+ public void endVisit(FunctionExpression node) {
+ // default implementation: do nothing
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AbstractTypeDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AbstractTypeDeclaration.java
new file mode 100644
index 0000000..9fe8daa
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AbstractTypeDeclaration.java
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.List;
+
+/**
+ * Abstract subclass for type declaration AST node types.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class AbstractTypeDeclaration extends BodyDeclaration {
+
+
+ /**
+ * The type name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript class identifier.
+ */
+ SimpleName typeName = null;
+
+ /**
+ * The body declarations (element type: BodyDeclaration
).
+ * Defaults to an empty list.
+ */
+ ASTNode.NodeList bodyDeclarations;
+
+ /**
+ * Returns structural property descriptor for the "bodyDeclarations" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildListPropertyDescriptor internalBodyDeclarationsProperty();
+
+ /**
+ * Returns structural property descriptor for the "bodyDeclarations" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ public final ChildListPropertyDescriptor getBodyDeclarationsProperty() {
+ return internalBodyDeclarationsProperty();
+ }
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildPropertyDescriptor internalNameProperty();
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ public final ChildPropertyDescriptor getNameProperty() {
+ return internalNameProperty();
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "bodyDeclaration" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildListPropertyDescriptor internalBodyDeclarationPropertyFactory(Class nodeClass) {
+ return new ChildListPropertyDescriptor(nodeClass, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "name" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) {
+ return new ChildPropertyDescriptor(nodeClass, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new AST node for an abstract type declaration owned by the given
+ * AST.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ AbstractTypeDeclaration(AST ast) {
+ super(ast);
+ this.bodyDeclarations = new ASTNode.NodeList(internalBodyDeclarationsProperty());
+ }
+
+ /**
+ * Returns the name of the type declared in this type declaration.
+ *
+ * @return the type name node
+ */
+ public SimpleName getName() {
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, internalNameProperty());
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the name of the type declared in this type declaration to the
+ * given name.
+ *
+ * @param typeName the new type name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName typeName) {
+ if (typeName == null) {
+ throw new IllegalArgumentException();
+ }
+ ChildPropertyDescriptor p = internalNameProperty();
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, typeName, p);
+ this.typeName = typeName;
+ postReplaceChild(oldChild, typeName, p);
+ }
+
+ /**
+ * Returns the live ordered list of body declarations of this type
+ * declaration.
+ *
+ * @return the live list of body declarations
+ * (element type: BodyDeclaration
)
+ */
+ public List bodyDeclarations() {
+ return this.bodyDeclarations;
+ }
+
+ /**
+ * Returns whether this type declaration is a package member (that is,
+ * a top-level type).
+ *
+ * Note that this is a convenience method that simply checks whether
+ * this node's parent is a javaScript unit node.
+ *
+ *
+ * @return true
if this type declaration is a child of
+ * a javaScript unit node, and false
otherwise
+ */
+ public boolean isPackageMemberTypeDeclaration() {
+ ASTNode parent = getParent();
+ return (parent instanceof JavaScriptUnit);
+ }
+
+ /**
+ * Returns whether this type declaration is a type member.
+ *
+ * Note that this is a convenience method that simply checks whether
+ * this node's parent is a type declaration node or an anonymous
+ * class declaration.
+ *
+ *
+ * @return true
if this type declaration is a child of
+ * a type declaration node or an anonymous class declaration node,
+ * and false
otherwise
+ */
+ public boolean isMemberTypeDeclaration() {
+ ASTNode parent = getParent();
+ return (parent instanceof AbstractTypeDeclaration)
+ || (parent instanceof AnonymousClassDeclaration);
+ }
+
+ /**
+ * Returns whether this type declaration is a local type.
+ *
+ * Note that this is a convenience method that simply checks whether
+ * this node's parent is a type declaration statement node.
+ *
+ *
+ * @return true
if this type declaration is a child of
+ * a type declaration statement node, and false
otherwise
+ */
+ public boolean isLocalTypeDeclaration() {
+ ASTNode parent = getParent();
+ return (parent instanceof TypeDeclarationStatement);
+ }
+
+ /**
+ * Resolves and returns the binding for the type declared in this type
+ * declaration.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public final ITypeBinding resolveBinding() {
+ return internalResolveBinding();
+ }
+
+ /**
+ * Resolves and returns the binding for the type declared in this type
+ * declaration. This method must be implemented by subclasses.
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ abstract ITypeBinding internalResolveBinding();
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AnonymousClassDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AnonymousClassDeclaration.java
new file mode 100644
index 0000000..06dcd07
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/AnonymousClassDeclaration.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Anonymous class declaration AST node type. For JLS2, this type of node appears
+ * only as a child on a class instance creation expression.
+ * For JLS3, this type of node appears may also appear as the child of
+ * an enum constant declaration.
+ *
+ *
+ * AnonymousClassDeclaration:
+ * { ClassBodyDeclaration }
+ *
+ *
+ * @see ClassInstanceCreation
+ * @see EnumConstantDeclaration
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class AnonymousClassDeclaration extends ASTNode {
+
+ /**
+ * The "bodyDeclarations" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ new ChildListPropertyDescriptor(AnonymousClassDeclaration.class, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(AnonymousClassDeclaration.class, properyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The body declarations (element type: BodyDeclaration
).
+ * Defaults to none.
+ */
+ private ASTNode.NodeList bodyDeclarations =
+ new ASTNode.NodeList(BODY_DECLARATIONS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an anonymous class declaration owned
+ * by the given AST. By default, the list of body declarations is empty.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ AnonymousClassDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == BODY_DECLARATIONS_PROPERTY) {
+ return bodyDeclarations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ANONYMOUS_CLASS_DECLARATION;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ AnonymousClassDeclaration result = new AnonymousClassDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.bodyDeclarations().addAll(
+ ASTNode.copySubtrees(target, bodyDeclarations()));
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, bodyDeclarations);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of body declarations of this
+ * anonymous class declaration.
+ *
+ * @return the live list of body declarations
+ * (element type: BodyDeclaration
)
+ */
+ public List bodyDeclarations() {
+ return this.bodyDeclarations;
+ }
+
+ /**
+ * Resolves and returns the binding for the anonymous class declared in
+ * this declaration.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public ITypeBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 4;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + this.bodyDeclarations.listSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayAccess.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayAccess.java
new file mode 100644
index 0000000..e231a28
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayAccess.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array access expression AST node type.
+ *
+ *
+ * ArrayAccess:
+ * Expression [ Expression ]
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ArrayAccess extends Expression {
+
+ /**
+ * The "array" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ARRAY_PROPERTY =
+ new ChildPropertyDescriptor(ArrayAccess.class, "array", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "index" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor INDEX_PROPERTY =
+ new ChildPropertyDescriptor(ArrayAccess.class, "index", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(ArrayAccess.class, properyList);
+ addProperty(ARRAY_PROPERTY, properyList);
+ addProperty(INDEX_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The array expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression arrayExpression = null;
+
+ /**
+ * The index expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression indexExpression = null;
+
+ /**
+ * Creates a new unparented array access expression node owned by the given
+ * AST. By default, the array and index expresssions are unspecified,
+ * but legal.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayAccess(AST ast) {
+ super(ast);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == ARRAY_PROPERTY) {
+ if (get) {
+ return getArray();
+ } else {
+ setArray((Expression) child);
+ return null;
+ }
+ }
+ if (property == INDEX_PROPERTY) {
+ if (get) {
+ return getIndex();
+ } else {
+ setIndex((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_ACCESS;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayAccess result = new ArrayAccess(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setArray((Expression) getArray().clone(target));
+ result.setIndex((Expression) getIndex().clone(target));
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getArray());
+ acceptChild(visitor, getIndex());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the array expression of this array access expression.
+ *
+ * @return the array expression node
+ */
+ public Expression getArray() {
+ if (this.arrayExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.arrayExpression == null) {
+ preLazyInit();
+ this.arrayExpression = new SimpleName(this.ast);
+ postLazyInit(this.arrayExpression, ARRAY_PROPERTY);
+ }
+ }
+ }
+ return this.arrayExpression;
+ }
+
+ /**
+ * Sets the array expression of this array access expression.
+ *
+ * @param expression the array expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setArray(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an ArrayAccess may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.arrayExpression;
+ preReplaceChild(oldChild, expression, ARRAY_PROPERTY);
+ this.arrayExpression = expression;
+ postReplaceChild(oldChild, expression, ARRAY_PROPERTY);
+ }
+
+ /**
+ * Returns the index expression of this array access expression.
+ *
+ * @return the index expression node
+ */
+ public Expression getIndex() {
+ if (this.indexExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.indexExpression == null) {
+ preLazyInit();
+ this.indexExpression = new SimpleName(this.ast);
+ postLazyInit(this.indexExpression, INDEX_PROPERTY);
+ }
+ }
+ }
+ return this.indexExpression;
+ }
+
+ /**
+ * Sets the index expression of this array access expression.
+ *
+ * @param expression the index expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setIndex(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an ArrayAccess may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.indexExpression;
+ preReplaceChild(oldChild, expression, INDEX_PROPERTY);
+ this.indexExpression = expression;
+ postReplaceChild(oldChild, expression, INDEX_PROPERTY);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.arrayExpression == null ? 0 : getArray().treeSize())
+ + (this.indexExpression == null ? 0 : getIndex().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayCreation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayCreation.java
new file mode 100644
index 0000000..ccac604
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayCreation.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array creation expression AST node type.
+ * For JLS2:
+ *
+ * The mapping from JavaScript language syntax to AST nodes is as follows:
+ *
+ * - the type node is the array type of the creation expression,
+ * with one level of array per set of square brackets,
+ * - the dimension expressions are collected into the
dimensions
+ * list.
+ *
+ *
+ * For JLS3, type arguments are added:
+ *
+ * ArrayCreation:
+ * new PrimitiveType [ Expression ] { [ Expression ] } { [ ] }
+ * new TypeName [ < Type { , Type } > ]
+ * [ Expression ] { [ Expression ] } { [ ] }
+ * new PrimitiveType [ ] { [ ] } ArrayInitializer
+ * new TypeName [ < Type { , Type } > ]
+ * [ ] { [ ] } ArrayInitializer
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ArrayCreation extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ArrayCreation.class, "type", ArrayType.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "dimensions" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY =
+ new ChildListPropertyDescriptor(ArrayCreation.class, "dimensions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "initializer" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(ArrayCreation.class, "initializer", ArrayInitializer.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(ArrayCreation.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(DIMENSIONS_PROPERTY, properyList);
+ addProperty(INITIALIZER_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The array type; lazily initialized; defaults to a unspecified,
+ * legal array type.
+ */
+ private ArrayType arrayType = null;
+
+ /**
+ * The list of dimension expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList dimensions =
+ new ASTNode.NodeList(DIMENSIONS_PROPERTY);
+
+ /**
+ * The optional array initializer, or null
if none;
+ * defaults to none.
+ */
+ private ArrayInitializer optionalInitializer = null;
+
+ /**
+ * Creates a new AST node for an array creation expression owned by the
+ * given AST. By default, the array type is an unspecified 1-dimensional
+ * array, the list of dimensions is empty, and there is no array
+ * initializer.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayCreation(AST ast) {
+ super(ast);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((ArrayInitializer) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((ArrayType) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == DIMENSIONS_PROPERTY) {
+ return dimensions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_CREATION;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayCreation result = new ArrayCreation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setType((ArrayType) getType().clone(target));
+ result.dimensions().addAll(ASTNode.copySubtrees(target, dimensions()));
+ result.setInitializer(
+ (ArrayInitializer) ASTNode.copySubtree(target, getInitializer()));
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.dimensions);
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the array type in this array creation expression.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return the array type
+ */
+ public ArrayType getType() {
+ if (this.arrayType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.arrayType == null) {
+ preLazyInit();
+ this.arrayType = this.ast.newArrayType(
+ this.ast.newInferredType(null));
+ postLazyInit(this.arrayType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.arrayType;
+ }
+
+ /**
+ * Sets the array type in this array creation expression.
+ *
+ * @param type the new array type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(ArrayType type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ // an ArrayCreation cannot occur inside a ArrayType - cycles not possible
+ ASTNode oldChild = this.arrayType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.arrayType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of dimension expressions in this array
+ * initializer.
+ *
+ * @return the live list of dimension expressions
+ * (element type: Expression
)
+ */
+ public List dimensions() {
+ return this.dimensions;
+ }
+
+ /**
+ * Returns the array initializer of this array creation expression, or
+ * null
if there is none.
+ *
+ * @return the array initializer node, or null
if
+ * there is none
+ */
+ public ArrayInitializer getInitializer() {
+ return optionalInitializer;
+ }
+
+ /**
+ * Sets or clears the array initializer of this array creation expression.
+ *
+ * @param initializer the array initializer node, or null
+ * if there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setInitializer(ArrayInitializer initializer) {
+ // an ArrayCreation may occur inside an ArrayInitializer
+ // must check cycles
+ ASTNode oldChild = this.optionalInitializer;
+ preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ this.optionalInitializer = initializer;
+ postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ int size = memSize()
+ + (this.arrayType == null ? 0 : getType().treeSize())
+ + (this.optionalInitializer == null ? 0 : getInitializer().treeSize())
+ + this.dimensions.listSize();
+ return size;
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayInitializer.java
new file mode 100644
index 0000000..c316b56
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayInitializer.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array initializer AST node type.
+ *
+ *
+ * ArrayInitializer:
+ * { Expression { , Expression} { , }} }
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ArrayInitializer extends Expression {
+
+ /**
+ * The "expressions" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor EXPRESSIONS_PROPERTY =
+ new ChildListPropertyDescriptor(ArrayInitializer.class, "expressions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ArrayInitializer.class, properyList);
+ addProperty(EXPRESSIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList expressions =
+ new ASTNode.NodeList(EXPRESSIONS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an array initializer owned by the
+ * given AST. By default, the list of expressions is empty.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayInitializer(AST ast) {
+ super(ast);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == EXPRESSIONS_PROPERTY) {
+ return expressions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_INITIALIZER;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayInitializer result = new ArrayInitializer(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.expressions().addAll(ASTNode.copySubtrees(target, expressions()));
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.expressions);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of expressions in this array initializer.
+ *
+ * @return the live list of expressions
+ * (element type: Expression
)
+ */
+ public List expressions() {
+ return this.expressions;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.expressions.listSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayType.java
new file mode 100644
index 0000000..8cc0221
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ArrayType.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for an array type.
+ *
+ * Array types are expressed in a recursive manner, one dimension at a time.
+ *
+ *
+ * ArrayType:
+ * Type [ ]
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ArrayType extends Type {
+
+ /**
+ * The "componentType" structural property of this node type.
+ * Note: This Field only applies to ECMAScript 4 which is not yet supported
+ *
+ */
+ public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ArrayType.class, properyList);
+ addProperty(COMPONENT_TYPE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The component type; lazily initialized; defaults to a simple type with
+ * an unspecfied, but legal, name.
+ */
+ private Type componentType = null;
+
+ /**
+ * Creates a new unparented node for an array type owned by the given AST.
+ * By default, a 1-dimensional array of an unspecified simple type.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ArrayType(AST ast) {
+ super(ast);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == COMPONENT_TYPE_PROPERTY) {
+ if (get) {
+ return getComponentType();
+ } else {
+ setComponentType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ARRAY_TYPE;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ArrayType result = new ArrayType(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setComponentType((Type) getComponentType().clone(target));
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getComponentType());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the component type of this array type. The component type
+ * may be another array type.
+ *
+ * @return the component type node
+ */
+ public Type getComponentType() {
+ if (this.componentType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.componentType == null) {
+ preLazyInit();
+ this.componentType = new SimpleType(this.ast);
+ postLazyInit(this.componentType, COMPONENT_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.componentType;
+ }
+
+ /**
+ * Sets the component type of this array type. The component type
+ * may be another array type.
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @param componentType the component type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setComponentType(Type componentType) {
+ if (componentType == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.componentType;
+ preReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+ this.componentType = componentType;
+ postReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the element type of this array type. The element type is
+ * never an array type.
+ *
+ * This is a convenience method that descends a chain of nested array types
+ * until it reaches a non-array type.
+ *
+ *
+ * Note: This Method only applies to ECMAScript 4 which is not yet supported
+ *
+ * @return the component type node
+ */
+ public Type getElementType() {
+ Type t = getComponentType();
+ while (t.isArrayType()) {
+ t = ((ArrayType) t).getComponentType();
+ }
+ return t;
+ }
+
+ /**
+ * Returns the number of dimensions in this array type.
+ *
+ * This is a convenience method that descends a chain of nested array types
+ * until it reaches a non-array type.
+ *
+ *
+ * @return the number of dimensions (always positive)
+ */
+ public int getDimensions() {
+ Type t = getComponentType();
+ int dimensions = 1; // always include this array type
+ while (t.isArrayType()) {
+ dimensions++;
+ t = ((ArrayType) t).getComponentType();
+ }
+ return dimensions;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.componentType == null ? 0 : getComponentType().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Assignment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Assignment.java
new file mode 100644
index 0000000..0f11f13
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Assignment.java
@@ -0,0 +1,439 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Assignment expression AST node type.
+ *
+ *
+ * Assignment:
+ * Expression AssignmentOperator Expression
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class Assignment extends Expression {
+
+ /**
+ * Assignment operators (typesafe enumeration).
+ *
+ * AssignmentOperator:
+ * = ASSIGN
+ * += PLUS_ASSIGN
+ * -= MINUS_ASSIGN
+ * *= TIMES_ASSIGN
+ * /= DIVIDE_ASSIGN
+ * &= BIT_AND_ASSIGN
+ * |= BIT_OR_ASSIGN
+ * ^= BIT_XOR_ASSIGN
+ * %= REMAINDER_ASSIGN
+ * <<= LEFT_SHIFT_ASSIGN
+ * >>= RIGHT_SHIFT_SIGNED_ASSIGN
+ * >>>= RIGHT_SHIFT_UNSIGNED_ASSIGN
+ *
+ */
+ public static class Operator {
+
+ /**
+ * The name of the operator
+ */
+ private String op;
+
+ /**
+ * Creates a new assignment operator with the given name.
+ *
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ *
+ *
+ * @param op the character sequence for the operator
+ */
+ private Operator(String op) {
+ this.op = op;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return op;
+ }
+
+ /** = operator. */
+ public static final Operator ASSIGN = new Operator("=");//$NON-NLS-1$
+ /** += operator. */
+ public static final Operator PLUS_ASSIGN = new Operator("+=");//$NON-NLS-1$
+ /** -= operator. */
+ public static final Operator MINUS_ASSIGN = new Operator("-=");//$NON-NLS-1$
+ /** *= operator. */
+ public static final Operator TIMES_ASSIGN = new Operator("*=");//$NON-NLS-1$
+ /** /= operator. */
+ public static final Operator DIVIDE_ASSIGN = new Operator("/=");//$NON-NLS-1$
+ /** &= operator. */
+ public static final Operator BIT_AND_ASSIGN = new Operator("&=");//$NON-NLS-1$
+ /** |= operator. */
+ public static final Operator BIT_OR_ASSIGN = new Operator("|=");//$NON-NLS-1$
+ /** ^= operator. */
+ public static final Operator BIT_XOR_ASSIGN = new Operator("^=");//$NON-NLS-1$
+ /** %= operator. */
+ public static final Operator REMAINDER_ASSIGN = new Operator("%=");//$NON-NLS-1$
+ /** <<== operator. */
+ public static final Operator LEFT_SHIFT_ASSIGN =
+ new Operator("<<=");//$NON-NLS-1$
+ /** >>= operator. */
+ public static final Operator RIGHT_SHIFT_SIGNED_ASSIGN =
+ new Operator(">>=");//$NON-NLS-1$
+ /** >>>= operator. */
+ public static final Operator RIGHT_SHIFT_UNSIGNED_ASSIGN =
+ new Operator(">>>=");//$NON-NLS-1$
+
+ /**
+ * Returns the assignment operator corresponding to the given string,
+ * or null
if none.
+ *
+ * toOperator
is the converse of toString
:
+ * that is, Operator.toOperator(op.toString()) == op
for all
+ * operators op
.
+ *
+ *
+ * @param token the character sequence for the operator
+ * @return the assignment operator, or null
if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+
+ /**
+ * Map from token to operator (key type: String
;
+ * value type: Operator
).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ ASSIGN,
+ PLUS_ASSIGN,
+ MINUS_ASSIGN,
+ TIMES_ASSIGN,
+ DIVIDE_ASSIGN,
+ BIT_AND_ASSIGN,
+ BIT_OR_ASSIGN,
+ BIT_XOR_ASSIGN,
+ REMAINDER_ASSIGN,
+ LEFT_SHIFT_ASSIGN,
+ RIGHT_SHIFT_SIGNED_ASSIGN,
+ RIGHT_SHIFT_UNSIGNED_ASSIGN
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+ }
+
+ /**
+ * The "leftHandSide" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor LEFT_HAND_SIDE_PROPERTY =
+ new ChildPropertyDescriptor(Assignment.class, "leftHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "operator" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(Assignment.class, "operator", Assignment.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "rightHandSide" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor RIGHT_HAND_SIDE_PROPERTY =
+ new ChildPropertyDescriptor(Assignment.class, "rightHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(Assignment.class, properyList);
+ addProperty(LEFT_HAND_SIDE_PROPERTY, properyList);
+ addProperty(OPERATOR_PROPERTY, properyList);
+ addProperty(RIGHT_HAND_SIDE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The assignment operator; defaults to Assignment.Operator.ASSIGN
+ */
+ private Assignment.Operator assignmentOperator = Assignment.Operator.ASSIGN;
+
+ /**
+ * The left hand side; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression leftHandSide = null;
+
+ /**
+ * The right hand side; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression rightHandSide = null;
+
+ /**
+ * Creates a new AST node for an assignment expression owned by the given
+ * AST. By default, the node has an assignment operator, and unspecified
+ * left and right hand sides.
+ *
+ * @param ast the AST that is to own this node
+ */
+ Assignment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LEFT_HAND_SIDE_PROPERTY) {
+ if (get) {
+ return getLeftHandSide();
+ } else {
+ setLeftHandSide((Expression) child);
+ return null;
+ }
+ }
+ if (property == RIGHT_HAND_SIDE_PROPERTY) {
+ if (get) {
+ return getRightHandSide();
+ } else {
+ setRightHandSide((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ASSIGNMENT;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Assignment result = new Assignment(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setOperator(getOperator());
+ result.setLeftHandSide((Expression) getLeftHandSide().clone(target));
+ result.setRightHandSide((Expression) getRightHandSide().clone(target));
+ return result;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLeftHandSide());
+ acceptChild(visitor, getRightHandSide());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this assignment expression.
+ *
+ * @return the assignment operator
+ */
+ public Assignment.Operator getOperator() {
+ return this.assignmentOperator;
+ }
+
+ /**
+ * Sets the operator of this assignment expression.
+ *
+ * @param assignmentOperator the assignment operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(Assignment.Operator assignmentOperator) {
+ if (assignmentOperator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.assignmentOperator = assignmentOperator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the left hand side of this assignment expression.
+ *
+ * @return the left hand side node
+ */
+ public Expression getLeftHandSide() {
+ if (this.leftHandSide == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.leftHandSide == null) {
+ preLazyInit();
+ this.leftHandSide= new SimpleName(this.ast);
+ postLazyInit(this.leftHandSide, LEFT_HAND_SIDE_PROPERTY);
+ }
+ }
+ }
+ return this.leftHandSide;
+ }
+
+ /**
+ * Sets the left hand side of this assignment expression.
+ *
+ * @param expression the left hand side node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setLeftHandSide(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an Assignment may occur inside a Expression - must check cycles
+ ASTNode oldChild = this.leftHandSide;
+ preReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
+ this.leftHandSide = expression;
+ postReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
+ }
+
+ /**
+ * Returns the right hand side of this assignment expression.
+ *
+ * @return the right hand side node
+ */
+ public Expression getRightHandSide() {
+ if (this.rightHandSide == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.rightHandSide == null) {
+ preLazyInit();
+ this.rightHandSide= new SimpleName(this.ast);
+ postLazyInit(this.rightHandSide, RIGHT_HAND_SIDE_PROPERTY);
+ }
+ }
+ }
+ return this.rightHandSide;
+ }
+
+ /**
+ * Sets the right hand side of this assignment expression.
+ *
+ * @param expression the right hand side node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setRightHandSide(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ // an Assignment may occur inside a Expression - must check cycles
+ ASTNode oldChild = this.rightHandSide;
+ preReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
+ this.rightHandSide = expression;
+ postReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit jsdoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.leftHandSide == null ? 0 : getLeftHandSide().treeSize())
+ + (this.rightHandSide == null ? 0 : getRightHandSide().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BindingComparator.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BindingComparator.java
new file mode 100644
index 0000000..ec3c53d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BindingComparator.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.HashSet;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ImportBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding;
+
+/**
+ * Internal helper class for comparing bindings.
+ *
+ */
+class BindingComparator {
+
+ /**
+ * @param declaringElement
+ * @param declaringElement2
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(Binding declaringElement, Binding declaringElement2, HashSet visitedTypes) {
+ if (declaringElement instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ if (!(declaringElement2 instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)){
+ return false;
+ }
+ return isEqual((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) declaringElement,
+ (org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) declaringElement2,
+ visitedTypes);
+ } else if (declaringElement instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding) {
+ if (!(declaringElement2 instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding)) {
+ return false;
+ }
+ return isEqual((org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding) declaringElement,
+ (org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding) declaringElement2,
+ visitedTypes);
+ } else if (declaringElement instanceof VariableBinding) {
+ if (!(declaringElement2 instanceof VariableBinding)) {
+ return false;
+ }
+ return isEqual((VariableBinding) declaringElement,
+ (VariableBinding) declaringElement2);
+ } else if (declaringElement instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) {
+ if (!(declaringElement2 instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding)) {
+ return false;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding packageBinding = (org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) declaringElement;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding packageBinding2 = (org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) declaringElement2;
+ return CharOperation.equals(packageBinding.compoundName, packageBinding2.compoundName);
+ } else if (declaringElement instanceof ImportBinding) {
+ if (!(declaringElement2 instanceof ImportBinding)) {
+ return false;
+ }
+ ImportBinding importBinding = (ImportBinding) declaringElement;
+ ImportBinding importBinding2 = (ImportBinding) declaringElement2;
+ return importBinding.onDemand == importBinding2.onDemand
+ && CharOperation.equals(importBinding.compoundName, importBinding2.compoundName);
+ }
+ return false;
+ }
+
+ static boolean isEqual(org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding,
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding2) {
+ return isEqual(methodBinding, methodBinding2, new HashSet());
+ }
+
+ static boolean isEqual(org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding,
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding2,
+ HashSet visitedTypes) {
+ if (methodBinding == null) {
+ return methodBinding2 == null;
+ }
+ if (methodBinding2 == null) return false;
+ if ( CharOperation.equals(methodBinding.selector, methodBinding2.selector)
+ && isEqual(methodBinding.returnType, methodBinding2.returnType, visitedTypes)
+// && isEqual(methodBinding.thrownExceptions, methodBinding2.thrownExceptions, visitedTypes)
+ && isEqual(methodBinding.declaringClass, methodBinding2.declaringClass, visitedTypes)
+// && isEqual(methodBinding.typeVariables, methodBinding2.typeVariables, visitedTypes)
+ && isEqual(methodBinding.parameters, methodBinding2.parameters, visitedTypes))
+ return true;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding constructorBinding =null;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methBinding =null;
+ if (methodBinding.selector==TypeConstants.INIT)
+ {
+ constructorBinding=methodBinding;
+ methBinding=methodBinding2;
+ }
+ else if (methodBinding2.selector==TypeConstants.INIT)
+ {
+ constructorBinding=methodBinding2;
+ methBinding=methodBinding;
+
+ }
+ return (constructorBinding!=null &&
+ CharOperation.equals(methBinding.selector,constructorBinding.declaringClass.sourceName)
+ && isEqual(methBinding.parameters, constructorBinding.parameters, visitedTypes));
+
+ }
+
+ static boolean isEqual(VariableBinding variableBinding, VariableBinding variableBinding2) {
+ return (variableBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (variableBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+ && CharOperation.equals(variableBinding.name, variableBinding2.name)
+ && isEqual(variableBinding.type, variableBinding2.type)
+ && (variableBinding.id == variableBinding2.id);
+ }
+
+ static boolean isEqual(LocalVariableBinding variableBinding, LocalVariableBinding variableBinding2) {
+ return (variableBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (variableBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+ && CharOperation.equals(variableBinding.name, variableBinding2.name)
+ && isEqual(variableBinding.type, variableBinding2.type)
+ && (variableBinding.id == variableBinding2.id)
+ && (variableBinding.declaration == variableBinding2.declaration);
+ }
+
+ static boolean isEqual(FieldBinding fieldBinding, FieldBinding fieldBinding2) {
+ HashSet visitedTypes = new HashSet();
+ return (fieldBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (fieldBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+ && CharOperation.equals(fieldBinding.name, fieldBinding2.name)
+ && isEqual(fieldBinding.type, fieldBinding2.type, visitedTypes)
+ && isEqual(fieldBinding.declaringClass, fieldBinding2.declaringClass, visitedTypes);
+ }
+
+ /**
+ * @param bindings
+ * @param otherBindings
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[] otherBindings) {
+ return isEqual(bindings, otherBindings, new HashSet());
+ }
+ /**
+ * @param bindings
+ * @param otherBindings
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[] bindings, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[] otherBindings, HashSet visitedTypes) {
+ if (bindings == null) {
+ return otherBindings == null;
+ }
+ if (otherBindings == null) {
+ return false;
+ }
+ int length = bindings.length;
+ int otherLength = otherBindings.length;
+ if (length != otherLength) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (!isEqual(bindings[i], otherBindings[i], visitedTypes)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ static boolean isEqual(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding typeBinding2, HashSet visitedTypes) {
+ if (typeBinding == typeBinding2)
+ return true;
+ if (typeBinding == null || typeBinding2 == null)
+ return false;
+
+ switch (typeBinding.kind()) {
+ case Binding.BASE_TYPE :
+ if (!typeBinding2.isBaseType()) {
+ return false;
+ }
+ return typeBinding.id == typeBinding2.id;
+
+ case Binding.ARRAY_TYPE :
+ if (!typeBinding2.isArrayType()) {
+ return false;
+ }
+ return typeBinding.dimensions() == typeBinding2.dimensions()
+ && isEqual(typeBinding.leafComponentType(), typeBinding2.leafComponentType(), visitedTypes);
+
+ default :
+ if (!(typeBinding2 instanceof ReferenceBinding)) {
+ return false;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+ ReferenceBinding referenceBinding2 = (ReferenceBinding) typeBinding2;
+ char[] constantPoolName = referenceBinding.constantPoolName();
+ char[] constantPoolName2 = referenceBinding2.constantPoolName();
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=116833
+ if (constantPoolName == null) {
+ if (constantPoolName2 != null) {
+ return false;
+ }
+ if (!CharOperation.equals(referenceBinding.computeUniqueKey(), referenceBinding2.computeUniqueKey())) {
+ return false;
+ }
+ } else {
+ if (constantPoolName2 == null) {
+ return false;
+ }
+ if (!CharOperation.equals(constantPoolName, constantPoolName2)) {
+ return false;
+ }
+ }
+ return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+ && ((referenceBinding.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag))
+ == ((referenceBinding2.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag))
+ && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
+ }
+ }
+ /**
+ * @param typeBinding
+ * @param typeBinding2
+ * @return true if both parameters are equals, false otherwise
+ */
+ static boolean isEqual(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding typeBinding, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding typeBinding2) {
+ return isEqual(typeBinding, typeBinding2, new HashSet());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BindingResolver.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BindingResolver.java
new file mode 100644
index 0000000..c6ee9b1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BindingResolver.java
@@ -0,0 +1,787 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+
+/**
+ * A binding resolver is an internal mechanism for figuring out the binding
+ * for a major declaration, type, or name reference.
+ *
+ * The default implementation serves as the default binding resolver
+ * that does no resolving whatsoever. Internal subclasses do all the real work.
+ *
+ *
+ * @see AST#getBindingResolver
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class BindingResolver {
+
+ /**
+ * Creates a binding resolver.
+ */
+ BindingResolver() {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Finds the corresponding AST node from which the given binding originated.
+ * Returns null
if the binding does not correspond to any node
+ * in the javaScript unit.
+ *
+ * The following table indicates the expected node type for the various
+ * different kinds of bindings:
+ *
+ *
+ * - var/field - a
VariableDeclarationFragment
in a
+ * FieldDeclaration
+ * - local variable - a
SingleVariableDeclaration
, or
+ * a VariableDeclarationFragment
in a
+ * VariableDeclarationStatement
or
+ * VariableDeclarationExpression
+ * - function/method - a
FunctionDeclaration
+ *
+ *
+ *
+ *
+ * The implementation of JavaScriptUnit.findDeclaringNode
+ * forwards to this method.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param binding the binding
+ * @return the corresponding node where the bindings is declared,
+ * or null
if none
+ */
+ ASTNode findDeclaringNode(IBinding binding) {
+ return null;
+ }
+
+ /**
+ * Finds the corresponding AST node from which the given binding key originated.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param bindingKey the binding key
+ * @return the corresponding node where the bindings is declared,
+ * or null
if none
+ */
+ ASTNode findDeclaringNode(String bindingKey) {
+ return null;
+ }
+
+ /**
+ * Allows the user to get information about the given old/new pair of
+ * AST nodes.
+ *
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param currentNode the new node
+ * @return org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode
+ */
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+ return null;
+ }
+
+ /**
+ * Returns the new method binding corresponding to the given old method binding.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param methodBinding the old method binding
+ * @return the new method binding
+ */
+ IFunctionBinding getMethodBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding) {
+ return null;
+ }
+
+ /*
+ * Returns the new package binding corresponding to the given old package binding.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param packageBinding the old package binding
+ * @return the new package binding
+ */
+ IPackageBinding getPackageBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding packageBinding) {
+ return null;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given old type binding.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param referenceBinding the old type binding
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+ return null;
+ }
+
+
+ /**
+ * Returns the new type binding corresponding to the given variableDeclaration.
+ * This is used for recovered binding only.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param variableDeclaration the given variable declaration
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
+ return null;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given type. This is used for recovered binding
+ * only.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param type the given type
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(Type type) {
+ return null;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given recovered type binding.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param recoveredTypeBinding the recovered type binding
+ * @param dimensions the dimensions to add the to given type binding dimensions
+ * @return the new type binding
+ */
+ ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
+ return null;
+ }
+
+ /**
+ * Returns the new variable binding corresponding to the given old variable binding.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param binding the old variable binding
+ * @return the new variable binding
+ */
+ IVariableBinding getVariableBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding binding) {
+ return null;
+ }
+
+
+ /**
+ * Return the working copy owner for the receiver.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ * @return the working copy owner for the receiver
+ */
+ public WorkingCopyOwner getWorkingCopyOwner() {
+ return null;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(FunctionInvocation methodInvocation) {
+ return false;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation methodInvocation) {
+ return false;
+ }
+
+ /**
+ * Returns the validator lookup environment used by this binding resolver.
+ * Returns null
if none.
+ *
+ * @return the lookup environment used by this resolver, or null
if none.
+ */
+ LookupEnvironment lookupEnvironment() {
+ return null;
+ }
+
+ /**
+ * This method is used to record the scope and its corresponding node.
+ *
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ *
+ * @param astNode
+ */
+ void recordScope(ASTNode astNode, BlockScope blockScope) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Returns whether this expression node is the site of a boxing
+ * conversion (JLS3 5.1.7). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return true
if this expression is the site of a
+ * boxing conversion, or false
if either no boxing conversion
+ * is involved or if bindings were not requested when the AST was created
+ */
+ boolean resolveBoxing(Expression expression) {
+ return false;
+ }
+
+ /**
+ * Returns whether this expression node is the site of an unboxing
+ * conversion (JLS3 5.1.8). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return true
if this expression is the site of an
+ * unboxing conversion, or false
if either no unboxing
+ * conversion is involved or if bindings were not requested when the
+ * AST was created
+ */
+ boolean resolveUnboxing(Expression expression) {
+ return false;
+ }
+
+ /**
+ * Resolves and returns the compile-time constant expression value as
+ * specified in JLS2 15.28, if this expression has one. Constant expression
+ * values are unavailable unless bindings are requested when the AST is
+ * being built. If the type of the value is a primitive type, the result
+ * is the boxed equivalent (i.e., int returned as an Integer
);
+ * if the type of the value is String
, the result is the string
+ * itself. If the expression does not have a compile-time constant expression
+ * value, the result is null
.
+ *
+ * Resolving constant expressions takes into account the value of simple
+ * and qualified names that refer to constant variables (JLS2 4.12.4).
+ *
+ *
+ * Note 1: enum constants are not considered constant expressions either.
+ * The result is always null
for these.
+ *
+ *
+ * Note 2: Compile-time constant expressions cannot denote null
.
+ * So technically {@link NullLiteral} nodes are not constant expressions.
+ * The result is null
for these nonetheless.
+ *
+ *
+ * @return the constant expression value, or null
if this
+ * expression has no constant expression value or if bindings were not
+ * requested when the AST was created
+ */
+ Object resolveConstantExpressionValue(Expression expression) {
+ return null;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ *
+ * The implementation of
+ * ClassInstanceCreation.resolveConstructor
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param expression the expression of interest
+ * @return the binding for the constructor being invoked, or
+ * null
if no binding is available
+ */
+ IFunctionBinding resolveConstructor(ClassInstanceCreation expression) {
+ return null;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ *
+ * The implementation of
+ * ConstructorInvocation.resolveConstructor
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param expression the expression of interest
+ * @return the binding for the constructor being invoked, or
+ * null
if no binding is available
+ */
+ IFunctionBinding resolveConstructor(ConstructorInvocation expression) {
+ return null;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor being invoked.
+ *
+ * The implementation of
+ * SuperConstructorInvocation.resolveConstructor
+ * forwards to this method. Which constructor is invoked is often a function
+ * of the context in which the expression node is embedded as well as
+ * the expression subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param expression the expression of interest
+ * @return the binding for the constructor being invoked, or
+ * null
if no binding is available
+ */
+ IFunctionBinding resolveConstructor(SuperConstructorInvocation expression) {
+ return null;
+ }
+ /**
+ * Resolves the type of the given expression and returns the type binding
+ * for it.
+ *
+ * The implementation of Expression.resolveTypeBinding
+ * forwards to this method. The result is often a function of the context
+ * in which the expression node is embedded as well as the expression
+ * subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param expression the expression whose type is of interest
+ * @return the binding for the type of the given expression, or
+ * null
if no binding is available
+ */
+ ITypeBinding resolveExpressionType(Expression expression) {
+ return null;
+ }
+
+ /**
+ * Resolves the given field access and returns the binding for it.
+ *
+ * The implementation of FieldAccess.resolveFieldBinding
+ * forwards to this method. How the field resolves is often a function of
+ * the context in which the field access node is embedded as well as
+ * the field access subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param fieldAccess the field access of interest
+ * @return the binding for the given field access, or
+ * null
if no binding is available
+ */
+ IVariableBinding resolveField(FieldAccess fieldAccess) {
+ return null;
+ }
+
+ /**
+ * Resolves the given super field access and returns the binding for it.
+ *
+ * The implementation of SuperFieldAccess.resolveFieldBinding
+ * forwards to this method. How the field resolves is often a function of
+ * the context in which the super field access node is embedded as well as
+ * the super field access subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param fieldAccess the super field access of interest
+ * @return the binding for the given field access, or
+ * null
if no binding is available
+ */
+ IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+ return null;
+ }
+
+ /**
+ * Resolves the given import declaration and returns the binding for it.
+ *
+ * The implementation of ImportDeclaration.resolveBinding
+ * forwards to this method.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param importDeclaration the import declaration of interest
+ * @return the binding for the given package declaration, or
+ * the package binding (for on-demand imports) or type binding
+ * (for single-type imports), or null
if no binding is
+ * available
+ */
+ IBinding resolveImport(ImportDeclaration importDeclaration) {
+ return null;
+ }
+
+ /**
+ * Resolves the given method declaration and returns the binding for it.
+ *
+ * The implementation of FunctionDeclaration.resolveBinding
+ * forwards to this method. How the method resolves is often a function of
+ * the context in which the method declaration node is embedded as well as
+ * the method declaration subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param method the method or constructor declaration of interest
+ * @return the binding for the given method declaration, or
+ * null
if no binding is available
+ */
+ IFunctionBinding resolveMethod(FunctionDeclaration method) {
+ return null;
+ }
+
+ /**
+ * Resolves the given method invocation and returns the binding for it.
+ *
+ * The implementation of FunctionInvocation.resolveMethodBinding
+ * forwards to this method. How the method resolves is often a function of
+ * the context in which the method invocation node is embedded as well as
+ * the method invocation subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param method the method invocation of interest
+ * @return the binding for the given method invocation, or
+ * null
if no binding is available
+ */
+ IFunctionBinding resolveMethod(FunctionInvocation method) {
+ return null;
+ }
+
+ /**
+ * Resolves the given method invocation and returns the binding for it.
+ *
+ * The implementation of FunctionInvocation.resolveMethodBinding
+ * forwards to this method. How the method resolves is often a function of
+ * the context in which the method invocation node is embedded as well as
+ * the method invocation subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param method the method invocation of interest
+ * @return the binding for the given method invocation, or
+ * null
if no binding is available
+ */
+ IFunctionBinding resolveMethod(SuperMethodInvocation method) {
+ return null;
+ }
+
+ /**
+ * Resolves the given name and returns the type binding for it.
+ *
+ * The implementation of Name.resolveBinding
forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param name the name of interest
+ * @return the binding for the name, or null
if no binding is
+ * available
+ */
+ IBinding resolveName(Name name) {
+ return null;
+ }
+
+ /**
+ * Resolves the given package declaration and returns the binding for it.
+ *
+ * The implementation of PackageDeclaration.resolveBinding
+ * forwards to this method.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param pkg the package declaration of interest
+ * @return the binding for the given package declaration, or
+ * null
if no binding is available
+ */
+ IPackageBinding resolvePackage(PackageDeclaration pkg) {
+ return null;
+ }
+
+ /**
+ * Resolves the given reference and returns the binding for it.
+ *
+ * The implementation of MemberRef.resolveBinding
forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param ref the reference of interest
+ * @return the binding for the reference, or null
if no binding is
+ * available
+ */
+ IBinding resolveReference(MemberRef ref) {
+ return null;
+ }
+
+ /**
+ * Resolves the given reference and returns the binding for it.
+ *
+ * The implementation of FunctionRef.resolveBinding
forwards to
+ * this method. How the name resolves is often a function of the context
+ * in which the name node is embedded as well as the name itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param ref the reference of interest
+ * @return the binding for the reference, or null
if no binding is
+ * available
+ */
+ IBinding resolveReference(FunctionRef ref) {
+ return null;
+ }
+
+ /**
+ * Resolves the given anonymous class declaration and returns the binding
+ * for it.
+ *
+ * The implementation of AnonymousClassDeclaration.resolveBinding
+ * forwards to this method. How the declaration resolves is often a
+ * function of the context in which the declaration node is embedded as well
+ * as the declaration subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param type the anonymous class declaration of interest
+ * @return the binding for the given class declaration, or null
+ * if no binding is available
+ */
+ ITypeBinding resolveType(AnonymousClassDeclaration type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given type and returns the type binding for it.
+ *
+ * The implementation of Type.resolveBinding
+ * forwards to this method. How the type resolves is often a function
+ * of the context in which the type node is embedded as well as the type
+ * subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param type the type of interest
+ * @return the binding for the given type, or null
+ * if no binding is available
+ */
+ ITypeBinding resolveType(Type type) {
+ return null;
+ }
+
+ /**
+ * Resolves the given class or interface declaration and returns the binding
+ * for it.
+ *
+ * The implementation of TypeDeclaration.resolveBinding
+ * (and TypeDeclarationStatement.resolveBinding
) forwards
+ * to this method. How the type declaration resolves is often a function of
+ * the context in which the type declaration node is embedded as well as the
+ * type declaration subtree itself.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param type the class or interface declaration of interest
+ * @return the binding for the given type declaration, or null
+ * if no binding is available
+ */
+ ITypeBinding resolveType(TypeDeclaration type) {
+ return null;
+ }
+
+
+ ITypeBinding resolveType(JavaScriptUnit compilationUnit) {
+ return null;
+ }
+
+ /**
+ * Resolves the given variable declaration and returns the binding for it.
+ *
+ * The implementation of VariableDeclaration.resolveBinding
+ * forwards to this method. How the variable declaration resolves is often
+ * a function of the context in which the variable declaration node is
+ * embedded as well as the variable declaration subtree itself. VariableDeclaration
+ * declarations used as local variable, formal parameter and exception
+ * variables resolve to local variable bindings; variable declarations
+ * used to declare fields resolve to field bindings.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param variable the variable declaration of interest
+ * @return the binding for the given variable declaration, or
+ * null
if no binding is available
+ */
+ IVariableBinding resolveVariable(VariableDeclaration variable) {
+ return null;
+ }
+
+ IVariableBinding resolveVariable(VariableDeclarationStatement variable) {
+ return null;
+ }
+
+ /**
+ * Resolves the given well known type by name and returns the type binding
+ * for it.
+ *
+ * The implementation of AST.resolveWellKnownType
+ * forwards to this method.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param name the name of a well known type
+ * @return the corresponding type binding, or null if the
+ * named type is not considered well known or if no binding can be found
+ * for it
+ */
+ ITypeBinding resolveWellKnownType(String name) {
+ return null;
+ }
+
+
+ /**
+ * Answer an array type binding with the given type binding and the given
+ * dimensions.
+ *
+ * If the given type binding is an array binding, then the resulting dimensions is the given dimensions
+ * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
+ * dimensions.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param typeBinding the given type binding
+ * @param dimensions the given dimensions
+ * @return an array type binding with the given type binding and the given
+ * dimensions
+ * @throws IllegalArgumentException if the type binding represents the void
type binding
+ */
+ ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
+ return null;
+ }
+
+ /**
+ * Returns the javaScript unit scope used by this binding resolver.
+ * Returns null
if none.
+ *
+ * @return the javaScript unit scope by this resolver, or null
if none.
+ */
+ public CompilationUnitScope scope() {
+ return null;
+ }
+
+ /**
+ * Allows the user to store information about the given old/new pair of
+ * AST nodes.
+ *
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param newNode the new AST node
+ * @param oldASTNode the old AST node
+ */
+ void store(ASTNode newNode, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode oldASTNode) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Allows the user to update information about the given old/new pair of
+ * AST nodes.
+ *
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param node the old AST node
+ * @param newNode the new AST node
+ */
+ void updateKey(ASTNode node, ASTNode newNode) {
+ // default implementation: do nothing
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Block.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Block.java
new file mode 100644
index 0000000..07e07ef
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Block.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Block statement AST node type.
+ *
+ *
+ * Block:
+ * { { Statement } }
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class Block extends Statement {
+
+ /**
+ * The "statements" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(Block.class, "statements", Statement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(Block.class, properyList);
+ addProperty(STATEMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of statements (element type: Statement
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList statements =
+ new ASTNode.NodeList(STATEMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented block node owned by the given AST.
+ * By default, the block is empty.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Block(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == STATEMENTS_PROPERTY) {
+ return statements();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BLOCK;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Block result = new Block(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.statements().addAll(
+ ASTNode.copySubtrees(target, statements()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.statements);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live list of statements in this block. Adding and
+ * removing nodes from this list affects this node dynamically.
+ * All nodes in this list must be Statement
s;
+ * attempts to add any other type of node will trigger an
+ * exception.
+ *
+ * @return the live list of statements in this block
+ * (element type: Statement
)
+ */
+ public List statements() {
+ return this.statements;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.statements.listSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BlockComment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BlockComment.java
new file mode 100644
index 0000000..3f10f55
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BlockComment.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Block comment AST node type.
+ *
+ * Block comments (also called "traditional" comments in JLS 3.7)
+ * begin with "/*", may contain line breaks, and must end
+ * with "*/". Block comment normally exclude comments
+ * that begin with "/*#42;", which are instead classified as doc
+ * comments ({@link JSdoc}).
+ *
+ *
+ * Note that this node type is a comment placeholder, and is
+ * only useful for recording the source range where a comment
+ * was found in a source string. It is not useful for creating
+ * comments.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class BlockComment extends Comment {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(1);
+ createPropertyList(BlockComment.class, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new block comment node owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ BlockComment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BLOCK_COMMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ BlockComment result = new BlockComment(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BodyDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BodyDeclaration.java
new file mode 100644
index 0000000..d63349a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BodyDeclaration.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract base class of all AST nodes that represent body declarations
+ * that may appear in the body of some kind of class or interface declaration,
+ * including anonymous class declarations.
+ *
+ *
+ * BodyDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * FunctionDeclaration
+ * ConstructorDeclaration
+ * FieldDeclaration
+ * Initializer
+ *
+ *
+ *
+ * All types of body declarations carry modifiers, although they differ in
+ * which modifiers are allowed. Most types of body declarations can carry a
+ * doc comment; Initializer is the only ones that does not. The source range
+ * for body declarations always includes the doc comment if present.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class BodyDeclaration extends ProgramElement {
+
+ /**
+ * The doc comment, or null
if none.
+ * Defaults to none.
+ */
+ JSdoc optionalDocComment = null;
+
+ /**
+ * The modifier flags; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in 3.0.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The extended modifiers (element type: IExtendedModifier
).
+ * defaults to an empty list
+ * (see constructor).
+ *
+ */
+ ASTNode.NodeList modifiers = null;
+
+ /**
+ * Returns structural property descriptor for the "modifiers" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract SimplePropertyDescriptor internalModifiersProperty();
+
+ /**
+ * Returns structural property descriptor for the "modifiers" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildListPropertyDescriptor internalModifiers2Property();
+
+ /**
+ * Returns structural property descriptor for the "modifiers" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ public final ChildListPropertyDescriptor getModifiersProperty() {
+ // important: return property for AST.JLS3
+ return internalModifiers2Property();
+ }
+
+ /**
+ * Returns structural property descriptor for the "jsdoc" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ abstract ChildPropertyDescriptor internalJavadocProperty();
+
+ /**
+ * Returns structural property descriptor for the "jsdoc" property
+ * of this node.
+ *
+ * @return the property descriptor
+ */
+ public final ChildPropertyDescriptor getJavadocProperty() {
+ return internalJavadocProperty();
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "jsdoc" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildPropertyDescriptor internalJavadocPropertyFactory(Class nodeClass) {
+ return new ChildPropertyDescriptor(nodeClass, "javadoc", JSdoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "modifiers" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final SimplePropertyDescriptor internalModifiersPropertyFactory(Class nodeClass) {
+ return new SimplePropertyDescriptor(nodeClass, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates and returns a structural property descriptor for the
+ * "modifiers" property declared on the given concrete node type.
+ *
+ * @return the property descriptor
+ */
+ static final ChildListPropertyDescriptor internalModifiers2PropertyFactory(Class nodeClass) {
+ return new ChildListPropertyDescriptor(nodeClass, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates a new AST node for a body declaration node owned by the
+ * given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ BodyDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(internalModifiers2Property());
+ }
+ }
+
+ /**
+ * Returns the doc comment node.
+ *
+ * @return the doc comment node, or null
if none
+ */
+ public JSdoc getJavadoc() {
+ return this.optionalDocComment;
+ }
+
+ /**
+ * Sets or clears the doc comment node.
+ *
+ * @param docComment the doc comment node, or null
if none
+ * @exception IllegalArgumentException if the doc comment string is invalid
+ */
+ public void setJavadoc(JSdoc docComment) {
+ ChildPropertyDescriptor p = internalJavadocProperty();
+ ASTNode oldChild = this.optionalDocComment;
+ preReplaceChild(oldChild, docComment, p);
+ this.optionalDocComment = docComment;
+ postReplaceChild(oldChild, docComment, p);
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ *
+ * @return the bit-wise or of Modifier
constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenience method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedmodifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedmodifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedmodifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ *
+ * @param modifiers the given modifiers (bit-wise or of Modifier
constants)
+ * @see Modifier
+ * @deprecated Rhis method is replaced by
+ * {@link #modifiers()} which contains a list of a Modifier
nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ // more efficient than just calling supportedOnlyIn2() to check
+ if (this.modifiers != null) {
+ supportedOnlyIn2();
+ }
+ SimplePropertyDescriptor p = internalModifiersProperty();
+ preValueChange(p);
+ this.modifierFlags = pmodifiers;
+ postValueChange(p);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers
+ * of this declaration .
+ *
+ * @return the live list of modifiers
+ * (element type: IExtendedModifier
)
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BooleanLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BooleanLiteral.java
new file mode 100644
index 0000000..7cbe3f6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BooleanLiteral.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Boolean literal node.
+ *
+ *
+ * BooleanLiteral:
+ * true
+ * false
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class BooleanLiteral extends Expression {
+
+ /**
+ * The "booleanValue" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor BOOLEAN_VALUE_PROPERTY =
+ new SimplePropertyDescriptor(BooleanLiteral.class, "booleanValue", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(BooleanLiteral.class, properyList);
+ addProperty(BOOLEAN_VALUE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The boolean; defaults to the literal for false
.
+ */
+ private boolean value = false;
+
+ /**
+ * Creates a new unparented boolean literal node owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ BooleanLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean newValue) {
+ if (property == BOOLEAN_VALUE_PROPERTY) {
+ if (get) {
+ return booleanValue();
+ } else {
+ setBooleanValue(newValue);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, newValue);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BOOLEAN_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ BooleanLiteral result = new BooleanLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setBooleanValue(booleanValue());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the boolean value of this boolean literal node.
+ *
+ * @return true
for the boolean literal spelled
+ * "true"
, and false
for the boolean literal
+ * spelled "false"
.
+ */
+ public boolean booleanValue() {
+ return this.value;
+ }
+
+ /**
+ * Sets the boolean value of this boolean literal node.
+ *
+ * @param value true
for the boolean literal spelled
+ * "true"
, and false
for the boolean literal
+ * spelled "false"
.
+ */
+ public void setBooleanValue(boolean value) {
+ preValueChange(BOOLEAN_VALUE_PROPERTY);
+ this.value = value;
+ postValueChange(BOOLEAN_VALUE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BreakStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BreakStatement.java
new file mode 100644
index 0000000..5f13cfe
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/BreakStatement.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Break statement AST node type.
+ *
+ *
+ * BreakStatement:
+ * break [ Identifier ] ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class BreakStatement extends Statement {
+
+ /**
+ * The "label" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor LABEL_PROPERTY =
+ new ChildPropertyDescriptor(BreakStatement.class, "label", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(BreakStatement.class, properyList);
+ addProperty(LABEL_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The label, or null
if none; none by default.
+ */
+ private SimpleName optionalLabel = null;
+
+ /**
+ * Creates a new unparented break statement node owned by the given
+ * AST. By default, the break statement has no label.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ BreakStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LABEL_PROPERTY) {
+ if (get) {
+ return getLabel();
+ } else {
+ setLabel((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return BREAK_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ BreakStatement result = new BreakStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getLabel());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the label of this break statement, or null
if
+ * there is none.
+ *
+ * @return the label, or null
if there is none
+ */
+ public SimpleName getLabel() {
+ return this.optionalLabel;
+ }
+
+ /**
+ * Sets or clears the label of this break statement.
+ *
+ * @param label the label, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setLabel(SimpleName label) {
+ ASTNode oldChild = this.optionalLabel;
+ preReplaceChild(oldChild, label, LABEL_PROPERTY);
+ this.optionalLabel = label;
+ postReplaceChild(oldChild, label, LABEL_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalLabel == null ? 0 : getLabel().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/CatchClause.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/CatchClause.java
new file mode 100644
index 0000000..f88f289
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/CatchClause.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Catch clause AST node type.
+ *
+ *
+ * CatchClause:
+ * catch ( FormalParameter ) Block
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class CatchClause extends ASTNode {
+
+ /**
+ * The "exception" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor EXCEPTION_PROPERTY =
+ new ChildPropertyDescriptor(CatchClause.class, "exception", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(CatchClause.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(CatchClause.class, properyList);
+ addProperty(EXCEPTION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * The exception variable declaration; lazily initialized; defaults to a
+ * unspecified, but legal, variable declaration.
+ */
+ private SingleVariableDeclaration exceptionDecl = null;
+
+ /**
+ * Creates a new AST node for a catch clause owned by the given
+ * AST. By default, the catch clause declares an unspecified, but legal,
+ * exception declaration and has an empty block.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ CatchClause(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXCEPTION_PROPERTY) {
+ if (get) {
+ return getException();
+ } else {
+ setException((SingleVariableDeclaration) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CATCH_CLAUSE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ CatchClause result = new CatchClause(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setBody((Block) getBody().clone(target));
+ result.setException(
+ (SingleVariableDeclaration) ASTNode.copySubtree(target, getException()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getException());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the exception variable declaration of this catch clause.
+ *
+ * @return the exception variable declaration node
+ */
+ public SingleVariableDeclaration getException() {
+ if (this.exceptionDecl == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.exceptionDecl == null) {
+ preLazyInit();
+ this.exceptionDecl = new SingleVariableDeclaration(this.ast);
+ postLazyInit(this.exceptionDecl, EXCEPTION_PROPERTY);
+ }
+ }
+ }
+ return this.exceptionDecl;
+ }
+
+ /**
+ * Sets the variable declaration of this catch clause.
+ *
+ * @param exception the exception variable declaration node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setException(SingleVariableDeclaration exception) {
+ if (exception == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.exceptionDecl;
+ preReplaceChild(oldChild, exception, EXCEPTION_PROPERTY);
+ this.exceptionDecl= exception;
+ postReplaceChild(oldChild, exception, EXCEPTION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this catch clause.
+ *
+ * @return the catch clause body
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this catch clause.
+ *
+ * @param body the catch clause block node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Block body) {
+ if (body == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.body = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.exceptionDecl == null ? 0 : getException().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/CharacterLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/CharacterLiteral.java
new file mode 100644
index 0000000..0582276
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/CharacterLiteral.java
@@ -0,0 +1,389 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Character literal nodes.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class CharacterLiteral extends Expression {
+
+ /**
+ * The "escapedValue" structural property of this node type.
+ */
+ public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
+ new SimplePropertyDescriptor(CharacterLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(CharacterLiteral.class, properyList);
+ addProperty(ESCAPED_VALUE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The literal string, including quotes and escapes; defaults to the
+ * literal for the character 'X'.
+ */
+ private String escapedValue = "\'X\'";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented character literal node owned by the given AST.
+ * By default, the character literal denotes an unspecified character.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ CharacterLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == ESCAPED_VALUE_PROPERTY) {
+ if (get) {
+ return getEscapedValue();
+ } else {
+ setEscapedValue((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CHARACTER_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ CharacterLiteral result = new CharacterLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setEscapedValue(getEscapedValue());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the string value of this literal node. The value is the sequence
+ * of characters that would appear in the source program, including
+ * enclosing single quotes and embedded escapes.
+ *
+ * @return the escaped string value, including enclosing single quotes
+ * and embedded escapes
+ */
+ public String getEscapedValue() {
+ return this.escapedValue;
+ }
+
+ /**
+ * Sets the string value of this literal node. The value is the sequence
+ * of characters that would appear in the source program, including
+ * enclosing single quotes and embedded escapes. For example,
+ *
+ * 'a'
setEscapedValue("\'a\'")
+ * '\n'
setEscapedValue("\'\\n\'")
+ *
+ *
+ * @param value the string value, including enclosing single quotes
+ * and embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setEscapedValue(String value) {
+ // check setInternalEscapedValue(String) if this method is changed
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = value.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameCharacterLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = value;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+ */
+ void internalSetEscapedValue(String value) {
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = value;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+ /**
+ * Returns the value of this literal node.
+ *
+ * For example,
+ *
+ * CharacterLiteral s;
+ * s.setEscapedValue("\'x\'");
+ * assert s.charValue() == 'x';
+ *
+ *
+ *
+ * @return the character value without enclosing quotes and embedded
+ * escapes
+ * @exception IllegalArgumentException if the literal value cannot be converted
+ */
+ public char charValue() {
+ Scanner scanner = this.ast.scanner;
+ char[] source = escapedValue.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ int firstChar = scanner.getNextChar();
+ int secondChar = scanner.getNextChar();
+
+ if (firstChar == -1 || firstChar != '\'') {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ char value = (char) secondChar;
+ char nextChar = (char) scanner.getNextChar();
+ if (secondChar == '\\') {
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ switch(nextChar) {
+ case 'b' :
+ value = '\b';
+ break;
+ case 't' :
+ value = '\t';
+ break;
+ case 'n' :
+ value = '\n';
+ break;
+ case 'f' :
+ value = '\f';
+ break;
+ case 'r' :
+ value = '\r';
+ break;
+ case '\"':
+ value = '\"';
+ break;
+ case '\'':
+ value = '\'';
+ break;
+ case '\\':
+ value = '\\';
+ break;
+ default : //octal (well-formed: ended by a ' )
+ try {
+ if (ScannerHelper.isDigit(nextChar)) {
+ int number = ScannerHelper.getNumericValue(nextChar);
+ nextChar = (char) scanner.getNextChar();
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ if (nextChar != '\'') {
+ if (!ScannerHelper.isDigit(nextChar)) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ number = (number * 8) + ScannerHelper.getNumericValue(nextChar);
+ nextChar = (char) scanner.getNextChar();
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ if (nextChar != '\'') {
+ if (!ScannerHelper.isDigit(nextChar)) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ number = (number * 8) + ScannerHelper.getNumericValue(nextChar);
+ }
+ }
+ return (char) number;
+ } else {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ } catch (InvalidInputException e) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ }
+ nextChar = (char) scanner.getNextChar();
+ if (nextChar == -1) {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ }
+ if (nextChar == -1 || nextChar != '\'') {
+ throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+ }
+ return value;
+ }
+ /**
+ * Sets the value of this character literal node to the given character.
+ *
+ * For example,
+ *
+ * CharacterLiteral s;
+ * s.setCharValue('x');
+ * assert s.charValue() == 'x';
+ * assert s.getEscapedValue("\'x\'");
+ *
+ *
+ *
+ * @param value the character value
+ */
+ public void setCharValue(char value) {
+ StringBuffer b = new StringBuffer(3);
+
+ b.append('\''); // opening delimiter
+ switch(value) {
+ case '\b' :
+ b.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ b.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ b.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ b.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ b.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\"':
+ b.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ b.append("\\\'"); //$NON-NLS-1$
+ break;
+ case '\\':
+ b.append("\\\\"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ b.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ b.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ b.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ b.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ b.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ b.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ b.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ b.append("\\7"); //$NON-NLS-1$
+ break;
+ default:
+ b.append(value);
+ }
+ b.append('\''); // closing delimiter
+ setEscapedValue(b.toString());
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(escapedValue);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ChildListPropertyDescriptor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ChildListPropertyDescriptor.java
new file mode 100644
index 0000000..2aa2ba7
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ChildListPropertyDescriptor.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Descriptor for a child list property of an AST node.
+ * A child list property is one whose value is a list of
+ * {@link ASTNode}.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class ChildListPropertyDescriptor extends StructuralPropertyDescriptor {
+
+ /**
+ * Element type. For example, for a node type like
+ * JavaScriptUnit, the "statements" property is Statement.class.
+ *
+ * Field is private, but marked package-visible for fast
+ * access from ASTNode.
+ *
+ */
+ final Class elementType;
+
+ /**
+ * Indicates whether a cycle is possible.
+ *
+ * Field is private, but marked package-visible for fast
+ * access from ASTNode.
+ *
+ */
+ final boolean cycleRisk;
+
+ /**
+ * Creates a new child list property descriptor with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ * @param elementType the element type of this property
+ * @param cycleRisk true
if this property is at
+ * risk of cycles, and false
if there is no worry about cycles
+ */
+ ChildListPropertyDescriptor(Class nodeClass, String propertyId, Class elementType, boolean cycleRisk) {
+ super(nodeClass, propertyId);
+ if (elementType == null) {
+ throw new IllegalArgumentException();
+ }
+ this.elementType = elementType;
+ this.cycleRisk = cycleRisk;
+ }
+
+ /**
+ * Returns the element type of this list property.
+ *
+ * For example, for a node type like JavaScriptUnit,
+ * the "imports" property returns ImportDeclaration.class
.
+ *
+ *
+ * @return the element type of the property
+ */
+ public final Class getElementType() {
+ return this.elementType;
+ }
+
+ /**
+ * Returns whether this property is vulnerable to cycles.
+ *
+ * A property is vulnerable to cycles if a node of the owning
+ * type (that is, the type that owns this property) could legally
+ * appear in the AST subtree below this property. For example,
+ * the body property of a
+ * {@link FunctionDeclaration} node
+ * admits a body which might include statement that embeds
+ * another {@link FunctionDeclaration} node.
+ * On the other hand, the name property of a
+ * FunctionDeclaration node admits only names, and thereby excludes
+ * another FunctionDeclaration node.
+ *
+ *
+ * @return true
if cycles are possible,
+ * and false
if cycles are impossible
+ */
+ public final boolean cycleRisk() {
+ return this.cycleRisk;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ChildPropertyDescriptor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ChildPropertyDescriptor.java
new file mode 100644
index 0000000..8e32eb5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ChildPropertyDescriptor.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Descriptor for a child property of an AST node.
+ * A child property is one whose value is an
+ * {@link ASTNode}.
+ *
+ * @see org.eclipse.wst.jsdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @see org.eclipse.wst.jsdt.core.dom.ASTNode#setStructuralProperty(StructuralPropertyDescriptor, Object)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class ChildPropertyDescriptor extends StructuralPropertyDescriptor {
+
+ /**
+ * Child type. For example, for a node type like
+ * JavaScriptUnit, the "package" property is PackageDeclaration.class
+ */
+ private final Class childClass;
+
+ /**
+ * Indicates whether the child is mandatory. A child property is allowed
+ * to be null
only if it is not mandatory.
+ */
+ private final boolean mandatory;
+
+ /**
+ * Indicates whether a cycle is possible.
+ * Field is private, but marked package-visible for fast
+ * access from ASTNode.
+ */
+ final boolean cycleRisk;
+
+ /**
+ * Creates a new child property descriptor with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ * @param childType the child type of this property
+ * @param mandatory true
if the property is mandatory,
+ * and false
if it is may be null
+ * @param cycleRisk true
if this property is at
+ * risk of cycles, and false
if there is no worry about cycles
+ */
+ ChildPropertyDescriptor(Class nodeClass, String propertyId, Class childType, boolean mandatory, boolean cycleRisk) {
+ super(nodeClass, propertyId);
+ if (childType == null || !ASTNode.class.isAssignableFrom(childType)) {
+ throw new IllegalArgumentException();
+ }
+ this.childClass = childType;
+ this.mandatory = mandatory;
+ this.cycleRisk = cycleRisk;
+ }
+
+ /**
+ * Returns the child type of this property.
+ *
+ * For example, for a node type like JavaScriptUnit,
+ * the "package" property returns PackageDeclaration.class
.
+ *
+ *
+ * @return the child type of the property
+ */
+ public final Class getChildType() {
+ return this.childClass;
+ }
+
+ /**
+ * Returns whether this property is mandatory. A property value
+ * is not allowed to be null
if it is mandatory.
+ *
+ * @return true
if the property is mandatory,
+ * and false
if it is may be null
+ */
+ public final boolean isMandatory() {
+ return this.mandatory;
+ }
+
+ /**
+ * Returns whether this property is vulnerable to cycles.
+ *
+ * A property is vulnerable to cycles if a node of the owning
+ * type (that is, the type that owns this property) could legally
+ * appear in the AST subtree below this property. For example,
+ * the body property of a
+ * {@link FunctionDeclaration} node
+ * admits a body which might include statement that embeds
+ * another {@link FunctionDeclaration} node.
+ * On the other hand, the name property of a
+ * FunctionDeclaration node admits only names, and thereby excludes
+ * another FunctionDeclaration node.
+ *
+ *
+ * @return true
if cycles are possible,
+ * and false
if cycles are impossible
+ */
+ public final boolean cycleRisk() {
+ return this.cycleRisk;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ClassInstanceCreation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ClassInstanceCreation.java
new file mode 100644
index 0000000..d993b00
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ClassInstanceCreation.java
@@ -0,0 +1,607 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Etienne Pfister - bug 231122
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class instance creation expression AST node type.
+ * For JLS2:
+ *
+ * ClassInstanceCreation:
+ * [ Expression . ] new Name
+ * ( [ Expression { , Expression } ] )
+ * [ AnonymousClassDeclaration ]
+ *
+ * For JLS3, type arguments are added
+ * and the type name is generalized to a type so that parameterized
+ * types can be instantiated:
+ *
+ * ClassInstanceCreation:
+ * [ Expression . ]
+ * new [ < Type { , Type } > ]
+ * Type ( [ Expression { , Expression } ] )
+ * [ AnonymousClassDeclaration ]
+ *
+ *
+ * Not all node arragements will represent legal JavaScript constructs. In particular,
+ * it is nonsense if the type is a primitive type or an array type (primitive
+ * types cannot be instantiated, and array creations must be represented with
+ * ArrayCreation
nodes). The normal use is when the type is a
+ * simple, qualified, or parameterized type.
+ *
+ *
+ * A type like "A.B" can be represented either of two ways:
+ *
+ * -
+ *
QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))
+ *
+ * -
+ *
SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))
+ *
+ *
+ * The first form is preferred when "A" is known to be a type (as opposed
+ * to a package). However, a parser cannot always determine this. Clients
+ * should be prepared to handle either rather than make assumptions.
+ * (Note also that the first form became possible as of JLS3; only the second
+ * form existed in JLS2.)
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ClassInstanceCreation extends Expression {
+
+ /**
+ * The "typeArguments" structural property of this node type .
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ClassInstanceCreation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type .
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type (added in JLS3 API).
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ClassInstanceCreation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "anonymousClassDeclaration" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ public static final ChildPropertyDescriptor MEMBER_PROPERTY =
+ new ChildPropertyDescriptor(ClassInstanceCreation.class, "member", AnonymousClassDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(ClassInstanceCreation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+ addProperty(MEMBER_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(6);
+ createPropertyList(ClassInstanceCreation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+ addProperty(MEMBER_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The optional expression; null
for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ private Expression member = null;
+
+ /**
+ * The type arguments (element type: Type
).
+ * Defaults to an empty list
+ * (see constructor).
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The type name; lazily initialized; defaults to a unspecified,
+ * legal type name.
+ */
+ private Name typeName = null;
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified type.
+ */
+ private Type type = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * The optional anonymous class declaration; null
for none;
+ * defaults to none.
+ */
+ private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
+
+ /**
+ * Creates a new AST node for a class instance creation expression owned
+ * by the given AST. By default, there is no qualifying expression,
+ * an empty list of type parameters, an unspecified type, an empty
+ * list of arguments, and does not declare an anonymous class.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ClassInstanceCreation (AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ if (property == MEMBER_PROPERTY) {
+ if (get) {
+ return getMember();
+ } else {
+ setMember((Expression) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
+ if (get) {
+ return getAnonymousClassDeclaration();
+ } else {
+ setAnonymousClassDeclaration((AnonymousClassDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CLASS_INSTANCE_CREATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ClassInstanceCreation result = new ClassInstanceCreation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ result.setMember(
+ (Expression) ASTNode.copySubtree(target, getMember()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setName((Name) getName().clone(target));
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+
+ Type type = getType();
+ if(type != null){
+ result.setType((Type) type.clone(target));
+ }
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ result.setAnonymousClassDeclaration(
+ (AnonymousClassDeclaration)
+ ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getMember());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ acceptChild(visitor, getName());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ acceptChild(visitor, getType());
+ }
+ acceptChildren(visitor, this.arguments);
+ acceptChild(visitor, getAnonymousClassDeclaration());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this class instance creation expression, or
+ * null
if there is none.
+ *
+ * @return the expression node, or null
if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ public Expression getMember() {
+ return this.member;
+ }
+
+ /**
+ * Sets or clears the expression of this class instance creation expression.
+ *
+ * @param expression the expression node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ // a ClassInstanceCreation may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ public void setMember(Expression expression) {
+ // a ClassInstanceCreation may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.member;
+ preReplaceChild(oldChild, expression, MEMBER_PROPERTY);
+ this.member = expression;
+ postReplaceChild(oldChild, expression, MEMBER_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this class
+ * instance creation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: Type
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the name of the type instantiated in this class instance
+ * creation expression (JLS2 API only).
+ *
+ * @return the type name node
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #getType()}, which returns a Type
instead of a
+ * Name
.
+ */
+ public Name getName() {
+ return internalGetName();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ */
+ /*package*/ Name internalGetName() {
+ supportedOnlyIn2();
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, NAME_PROPERTY);
+ }
+ }
+ }
+ return typeName;
+ }
+
+ /**
+ * Sets the name of the type instantiated in this class instance
+ * creation expression (JLS2 API only).
+ *
+ * @param name the new type name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
`
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setType(Type)}, which expects a Type
instead of
+ * a Name
.
+ */
+ public void setName(Name name) {
+ internalSetName(name);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ */
+ /*package*/ void internalSetName(Name name) {
+ supportedOnlyIn2();
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.typeName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the type instantiated in this class instance creation
+ * expression (added in JLS3 API).
+ *
+ * @return the type node
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public Type getType() {
+ unsupportedIn2();
+// if (this.type == null) {
+// // lazy init must be thread-safe for readers
+// synchronized (this) {
+// if (this.type == null) {
+// preLazyInit();
+// this.type = new SimpleType(this.ast);
+// postLazyInit(this.type, TYPE_PROPERTY);
+// }
+// }
+// }
+ return this.type;
+ }
+
+ /**
+ * Sets the type instantiated in this class instance creation
+ * expression (added in JLS3 API).
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
`
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public void setType(Type type) {
+ unsupportedIn2();
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this class
+ * instance creation expression.
+ *
+ * @return the live list of argument expressions (possibly empty)
+ * (element type: Expression
)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Returns the anonymous class declaration introduced by this
+ * class instance creation expression, if it has one.
+ *
+ * @return the anonymous class declaration, or null
if none
+ */
+ public AnonymousClassDeclaration getAnonymousClassDeclaration() {
+ return this.optionalAnonymousClassDeclaration;
+ }
+
+ /**
+ * Sets whether this class instance creation expression declares
+ * an anonymous class (that is, has class body declarations).
+ *
+ * @param decl the anonymous class declaration, or null
+ * if none
+ */
+ public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
+ ASTNode oldChild = this.optionalAnonymousClassDeclaration;
+ preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ this.optionalAnonymousClassDeclaration = decl;
+ postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * expression. For anonymous classes, the binding is that of the anonymous
+ * constructor.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the constructor binding, or null
if the binding
+ * cannot be resolved
+ */
+ public IFunctionBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 6 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ // n.b. type == null for ast.API_LEVEL == JLS2
+ // n.b. typeArguments == null for ast.API_LEVEL == JLS2
+ // n.b. typeName == null for ast.API_LEVEL >= JLS3
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + (this.type == null ? 0 : getType().treeSize())
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+ + (this.member == null ? 0 : getMember().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize())
+ + (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Comment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Comment.java
new file mode 100644
index 0000000..a3eafa7
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Comment.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Abstract base class for all AST nodes that represent comments.
+ * There are exactly three kinds of comment:
+ * line comments ({@link LineComment}),
+ * block comments ({@link BlockComment}), and
+ * doc comments ({@link JSdoc}).
+ *
+ *
+ * Comment:
+ * LineComment
+ * BlockComment
+ * JSdoc
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class Comment extends ASTNode {
+
+ /**
+ * Alternate root node, or null
if none.
+ * Initially null
.
+ */
+ private ASTNode alternateRoot = null;
+
+ /**
+ * Creates a new AST node for a comment owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Comment(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns whether this comment is a block comment
+ * (BlockComment
).
+ *
+ * @return true
if this is a block comment, and
+ * false
otherwise
+ */
+ public final boolean isBlockComment() {
+ return (this instanceof BlockComment);
+ }
+
+ /**
+ * Returns whether this comment is a line comment
+ * (LineComment
).
+ *
+ * @return true
if this is a line comment, and
+ * false
otherwise
+ */
+ public final boolean isLineComment() {
+ return (this instanceof LineComment);
+ }
+
+ /**
+ * Returns whether this comment is a doc comment
+ * (JSdoc
).
+ *
+ * @return true
if this is a doc comment, and
+ * false
otherwise
+ */
+ public final boolean isDocComment() {
+ return (this instanceof JSdoc);
+ }
+
+ /**
+ * Returns the root AST node that this comment occurs
+ * within, or null
if none (or not recorded).
+ *
+ * Typically, the comment nodes created while parsing a compilation
+ * unit are not considered descendents of the normal AST
+ * root, namely an {@link JavaScriptUnit}. Instead, these
+ * comment nodes exist outside the normal AST and each is
+ * a root in its own right. This optional property provides
+ * a well-known way to navigate from the comment to the
+ * javaScript unit in such cases. Note that the alternate root
+ * property is not one of the comment node's children. It is simply a
+ * reference to a node.
+ *
+ *
+ * @return the alternate root node, or null
+ * if none
+ * @see #setAlternateRoot(ASTNode)
+ */
+ public final ASTNode getAlternateRoot() {
+ return this.alternateRoot;
+ }
+
+ /**
+ * Returns the root AST node that this comment occurs
+ * within, or null
if none (or not recorded).
+ *
+ *
+ *
+ * @param root the alternate root node, or null
+ * if none
+ * @see #getAlternateRoot()
+ */
+ public final void setAlternateRoot(ASTNode root) {
+ // alternate root is *not* considered a structural property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.alternateRoot = root;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ConditionalExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ConditionalExpression.java
new file mode 100644
index 0000000..995ae43
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ConditionalExpression.java
@@ -0,0 +1,332 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Conditional expression AST node type.
+ *
+ *
+ * ConditionalExpression:
+ * Expression ? Expression : Expression
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ConditionalExpression extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ConditionalExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "thenExpression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor THEN_EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ConditionalExpression.class, "thenExpression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "elseExpression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor ELSE_EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ConditionalExpression.class, "elseExpression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(ConditionalExpression.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(THEN_EXPRESSION_PROPERTY, properyList);
+ addProperty(ELSE_EXPRESSION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The condition expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression conditionExpression = null;
+
+ /**
+ * The "then" expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression thenExpression = null;
+
+ /**
+ * The "else" expression; lazily initialized; defaults to an unspecified,
+ * but legal, expression.
+ */
+ private Expression elseExpression = null;
+
+ /**
+ * Creates a new unparented conditional expression node owned by the given
+ * AST. By default, the condition, "then", and "else" expresssions are
+ * unspecified, but legal.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ConditionalExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == THEN_EXPRESSION_PROPERTY) {
+ if (get) {
+ return getThenExpression();
+ } else {
+ setThenExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == ELSE_EXPRESSION_PROPERTY) {
+ if (get) {
+ return getElseExpression();
+ } else {
+ setElseExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CONDITIONAL_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ConditionalExpression result = new ConditionalExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setThenExpression(
+ (Expression) getThenExpression().clone(target));
+ result.setElseExpression(
+ (Expression) getElseExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getThenExpression());
+ acceptChild(visitor, getElseExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the condition of this conditional expression.
+ *
+ * @return the condition node
+ */
+ public Expression getExpression() {
+ if (this.conditionExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.conditionExpression == null) {
+ preLazyInit();
+ this.conditionExpression = new SimpleName(this.ast);
+ postLazyInit(this.conditionExpression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.conditionExpression;
+ }
+
+ /**
+ * Sets the condition of this conditional expression.
+ *
+ * @param expression the condition node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.conditionExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.conditionExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the "then" part of this conditional expression.
+ *
+ * @return the "then" expression node
+ */
+ public Expression getThenExpression() {
+ if (this.thenExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.thenExpression == null) {
+ preLazyInit();
+ this.thenExpression = new SimpleName(this.ast);
+ postLazyInit(this.thenExpression, THEN_EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.thenExpression;
+ }
+
+ /**
+ * Sets the "then" part of this conditional expression.
+ *
+ * @param expression the "then" expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setThenExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.thenExpression;
+ preReplaceChild(oldChild, expression, THEN_EXPRESSION_PROPERTY);
+ this.thenExpression = expression;
+ postReplaceChild(oldChild, expression, THEN_EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the "else" part of this conditional expression.
+ *
+ * @return the "else" expression node
+ */
+ public Expression getElseExpression() {
+ if (this.elseExpression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.elseExpression == null) {
+ preLazyInit();
+ this.elseExpression = new SimpleName(this.ast);
+ postLazyInit(this.elseExpression, ELSE_EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.elseExpression;
+ }
+
+ /**
+ * Sets the "else" part of this conditional expression.
+ *
+ * @param expression the "else" expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setElseExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.elseExpression;
+ preReplaceChild(oldChild, expression, ELSE_EXPRESSION_PROPERTY);
+ this.elseExpression = expression;
+ postReplaceChild(oldChild, expression, ELSE_EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.conditionExpression == null ? 0 : getExpression().treeSize())
+ + (this.thenExpression == null ? 0 : getThenExpression().treeSize())
+ + (this.elseExpression == null ? 0 : getElseExpression().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ConstructorInvocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ConstructorInvocation.java
new file mode 100644
index 0000000..747edb6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ConstructorInvocation.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Alternate constructor invocation statement AST node type.
+ * For JLS2:
+ *
+ * ConstructorInvocation:
+ * this ( [ Expression { , Expression } ] ) ;
+ *
+ * For JLS3, type arguments are added:
+ *
+ * ConstructorInvocation:
+ * [ < Type { , Type } > ]
+ * this ( [ Expression { , Expression } ] ) ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ConstructorInvocation extends Statement {
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ConstructorInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(ConstructorInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ConstructorInvocation.class, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(3);
+ createPropertyList(ConstructorInvocation.class, properyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The type arguments (element type: Type
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an alternate constructor invocation statement
+ * owned by the given AST. By default, an empty list of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ConstructorInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CONSTRUCTOR_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ConstructorInvocation result = new ConstructorInvocation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this constructor
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: Type
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this alternate
+ * constructor invocation statement.
+ *
+ * @return the live list of argument expressions
+ * (element type: Expression
)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the constructor binding, or null
if the binding
+ * cannot be resolved
+ */
+ public IFunctionBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ContinueStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ContinueStatement.java
new file mode 100644
index 0000000..43ff09f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ContinueStatement.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Continue statement AST node type.
+ *
+ *
+ * ContinueStatement:
+ * continue [ Identifier ] ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ContinueStatement extends Statement {
+
+ /**
+ * The "label" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor LABEL_PROPERTY =
+ new ChildPropertyDescriptor(ContinueStatement.class, "label", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ContinueStatement.class, properyList);
+ addProperty(LABEL_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The label, or null
if none; none by default.
+ */
+ private SimpleName optionalLabel = null;
+
+ /**
+ * Creates a new unparented continue statement node owned by the given
+ * AST. By default, the continue statement has no label.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ContinueStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LABEL_PROPERTY) {
+ if (get) {
+ return getLabel();
+ } else {
+ setLabel((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return CONTINUE_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ContinueStatement result = new ContinueStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getLabel());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the label of this continue statement, or null
if
+ * there is none.
+ *
+ * @return the label, or null
if there is none
+ */
+ public SimpleName getLabel() {
+ return this.optionalLabel;
+ }
+
+ /**
+ * Sets or clears the label of this continue statement.
+ *
+ * @param label the label, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setLabel(SimpleName label) {
+ ASTNode oldChild = this.optionalLabel;
+ preReplaceChild(oldChild, label, LABEL_PROPERTY);
+ this.optionalLabel = label;
+ postReplaceChild(oldChild, label, LABEL_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (optionalLabel == null ? 0 : getLabel().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultASTVisitor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultASTVisitor.java
new file mode 100644
index 0000000..590b50a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultASTVisitor.java
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+class DefaultASTVisitor extends ASTVisitor {
+
+
+ /**
+ *
+ */
+ public DefaultASTVisitor() {
+ super();
+ }
+
+ /**
+ *
+ */
+ public DefaultASTVisitor(boolean visitDocTags) {
+ super(visitDocTags);
+ }
+
+ public void endVisit(AnonymousClassDeclaration node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ArrayAccess node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ArrayCreation node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ArrayInitializer node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ArrayType node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(Assignment node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(Block node) {
+ endVisitNode(node);
+ }
+
+ /* since 3.0 */
+ public void endVisit(BlockComment node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(BooleanLiteral node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(BreakStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(CatchClause node) {
+ endVisitNode(node);
+ }
+ public void endVisit(CharacterLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ClassInstanceCreation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(JavaScriptUnit node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ConditionalExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ConstructorInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ContinueStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(DoStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(EmptyStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(EnhancedForStatement node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ExpressionStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FieldAccess node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FieldDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ForInStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ForStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FunctionExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(IfStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ImportDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(InferredType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(InfixExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(Initializer node) {
+ endVisitNode(node);
+ }
+ public void endVisit(InstanceofExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(JSdoc node) {
+ endVisitNode(node);
+ }
+ public void endVisit(LabeledStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(LineComment node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ListExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(MemberRef node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FunctionDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FunctionInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FunctionRef node) {
+ endVisitNode(node);
+ }
+ public void endVisit(FunctionRefParameter node) {
+ endVisitNode(node);
+ }
+ public void endVisit(NullLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(NumberLiteral node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ObjectLiteral node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(ObjectLiteralField node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PackageDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ParenthesizedExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PostfixExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PrefixExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(PrimitiveType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(QualifiedName node) {
+ endVisitNode(node);
+ }
+ public void endVisit(QualifiedType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(RegularExpressionLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ReturnStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SimpleName node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SimpleType node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SingleVariableDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(StringLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SuperConstructorInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SuperFieldAccess node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SuperMethodInvocation node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SwitchCase node) {
+ endVisitNode(node);
+ }
+ public void endVisit(SwitchStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TagElement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TextElement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ThisExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(ThrowStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TryStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TypeDeclaration node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TypeDeclarationStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(TypeLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(UndefinedLiteral node) {
+ endVisitNode(node);
+ }
+ public void endVisit(VariableDeclarationExpression node) {
+ endVisitNode(node);
+ }
+ public void endVisit(VariableDeclarationFragment node) {
+ endVisitNode(node);
+ }
+ public void endVisit(VariableDeclarationStatement node) {
+ endVisitNode(node);
+ }
+ public void endVisit(WhileStatement node) {
+ endVisitNode(node);
+ }
+
+ public void endVisit(WithStatement node) {
+ endVisitNode(node);
+ }
+ protected void endVisitNode(ASTNode node) {
+ // do nothing
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayAccess node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayCreation node) {
+ return visitNode(node);
+ }
+ public boolean visit(ArrayInitializer node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(ArrayType node) {
+ visitNode(node);
+ return false;
+ }
+ public boolean visit(Assignment node) {
+ return visitNode(node);
+ }
+ public boolean visit(Block node) {
+ return visitNode(node);
+ }
+ /* since 3.0 */
+ public boolean visit(BlockComment node) {
+ return visitNode(node);
+ }
+ public boolean visit(BooleanLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(BreakStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(CatchClause node) {
+ return visitNode(node);
+ }
+ public boolean visit(CharacterLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(ClassInstanceCreation node) {
+ return visitNode(node);
+ }
+ public boolean visit(JavaScriptUnit node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(ConditionalExpression node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(ConstructorInvocation node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(ContinueStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(DoStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(EmptyStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(EnhancedForStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(ExpressionStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(FieldAccess node) {
+ return visitNode(node);
+ }
+ public boolean visit(FieldDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ForInStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(ForStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(FunctionExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(IfStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(ImportDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(InferredType node) {
+ return visitNode(node);
+ }
+ public boolean visit(InfixExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(Initializer node) {
+ return visitNode(node);
+ }
+ public boolean visit(InstanceofExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(JSdoc node) {
+ // do not visit jsdoc tags by default. Use constructor with boolean to enable.
+ if (super.visit(node)) {
+ return visitNode(node);
+ }
+ return false;
+ }
+ public boolean visit(LabeledStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(LineComment node) {
+ return visitNode(node);
+ }
+ public boolean visit(ListExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(MemberRef node) {
+ return visitNode(node);
+ }
+ public boolean visit(FunctionDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(FunctionInvocation node) {
+ return visitNode(node);
+ }
+ public boolean visit(FunctionRef node) {
+ return visitNode(node);
+ }
+ public boolean visit(FunctionRefParameter node) {
+ return visitNode(node);
+ }
+ public boolean visit(NullLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(NumberLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(ObjectLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(ObjectLiteralField node) {
+ return visitNode(node);
+ }
+ public boolean visit(PackageDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(ParenthesizedExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(PostfixExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(PrefixExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(PrimitiveType node) {
+ return visitNode(node);
+ }
+ public boolean visit(QualifiedName node) {
+ return visitNode(node);
+ }
+ public boolean visit(QualifiedType node) {
+ return visitNode(node);
+ }
+ public boolean visit(RegularExpressionLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(ReturnStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(SimpleName node) {
+ return visitNode(node);
+ }
+ public boolean visit(SimpleType node) {
+ return visitNode(node);
+ }
+ public boolean visit(SingleVariableDeclaration node) {
+ return visitNode(node);
+ }
+ public boolean visit(StringLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(SuperConstructorInvocation node) {
+ return visitNode(node);
+ }
+ public boolean visit(SuperFieldAccess node) {
+ return visitNode(node);
+ }
+ public boolean visit(SuperMethodInvocation node) {
+ return visitNode(node);
+ }
+ public boolean visit(SwitchCase node) {
+ return visitNode(node);
+ }
+ public boolean visit(SwitchStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(TagElement node) {
+ return visitNode(node);
+ }
+ public boolean visit(TextElement node) {
+ return visitNode(node);
+ }
+ public boolean visit(ThisExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(ThrowStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(TryStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(TypeDeclaration node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TypeDeclarationStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(TypeLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(UndefinedLiteral node) {
+ return visitNode(node);
+ }
+ public boolean visit(VariableDeclarationExpression node) {
+ return visitNode(node);
+ }
+ public boolean visit(VariableDeclarationFragment node) {
+ return visitNode(node);
+ }
+ public boolean visit(VariableDeclarationStatement node) {
+ return visitNode(node);
+ }
+ public boolean visit(WhileStatement node) {
+ return visitNode(node);
+ }
+
+ public boolean visit(WithStatement node) {
+ return visitNode(node);
+ }
+
+ protected boolean visitNode(ASTNode node) {
+ return true;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultBindingResolver.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultBindingResolver.java
new file mode 100644
index 0000000..f023af3
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultBindingResolver.java
@@ -0,0 +1,1595 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocImplicitTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Literal;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+
+/**
+ * Internal class for resolving bindings using old ASTs.
+ *
+ * IMPORTANT: The methods on this class are synchronized. This is required
+ * because there may be multiple clients in separate threads concurrently
+ * reading an AST and asking for bindings for its nodes. These requests all
+ * end up invoking instance methods on this class. There are various internal
+ * tables and caches which are built and maintained in the course of looking
+ * up bindings. To ensure that they remain coherent in the presence of multiple
+ * threads, the methods are synchronized on the DefaultBindingResolver instance.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+class DefaultBindingResolver extends BindingResolver {
+
+ /*
+ * Holds on binding tables that can be shared by several ASTs.
+ */
+ static class BindingTables {
+
+ /**
+ * This map is used to get a binding from its binding key.
+ */
+ Map bindingKeysToBindings;
+ /**
+ * This map is used to keep the correspondance between new bindings and the
+ * validator bindings to their internal counterpart.
+ * This is an identity map. We should only create one object for one binding.
+ */
+ Map compilerBindingsToASTBindings;
+
+ BindingTables() {
+ this.compilerBindingsToASTBindings = new HashMap();
+ this.bindingKeysToBindings = new HashMap();
+ }
+
+ }
+ /**
+ * This map is used to retrieve the corresponding block scope for a ast node
+ */
+ Map astNodesToBlockScope;
+
+ /**
+ * This map is used to get an ast node from its binding (new binding) or DOM
+ */
+ Map bindingsToAstNodes;
+
+ /*
+ * The shared binding tables accros ASTs.
+ */
+ BindingTables bindingTables;
+
+ /**
+ * This map is used to retrieve an old ast node using the new ast node. This is not an
+ * identity map.
+ */
+ Map newAstToOldAst;
+
+ /**
+ * JavaScript unit scope
+ */
+ private CompilationUnitScope scope;
+
+ /**
+ * The working copy owner that defines the context in which this resolver is creating the bindings.
+ */
+ WorkingCopyOwner workingCopyOwner;
+ boolean isRecoveredBinding;
+
+
+ /**
+ * Constructor for DefaultBindingResolver.
+ */
+ DefaultBindingResolver(CompilationUnitScope scope, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveredBinding) {
+ this.newAstToOldAst = new HashMap();
+ this.astNodesToBlockScope = new HashMap();
+ this.bindingsToAstNodes = new HashMap();
+ this.bindingTables = bindingTables;
+ this.scope = scope;
+ this.workingCopyOwner = workingCopyOwner;
+ this.isRecoveredBinding = isRecoveredBinding;
+ }
+
+ DefaultBindingResolver(LookupEnvironment lookupEnvironment, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveredBinding) {
+ this.newAstToOldAst = new HashMap();
+ this.astNodesToBlockScope = new HashMap();
+ this.bindingsToAstNodes = new HashMap();
+ this.bindingTables = bindingTables;
+ this.scope = new CompilationUnitScope(new CompilationUnitDeclaration(null, null, -1), lookupEnvironment);
+ this.workingCopyOwner = workingCopyOwner;
+ this.isRecoveredBinding = isRecoveredBinding;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ASTNode findDeclaringNode(IBinding binding) {
+ if (binding == null) {
+ return null;
+ }
+ if (binding instanceof IFunctionBinding) {
+ IFunctionBinding methodBinding = (IFunctionBinding) binding;
+ return (ASTNode) this.bindingsToAstNodes.get(methodBinding.getMethodDeclaration());
+ } else if (binding instanceof ITypeBinding) {
+ ITypeBinding typeBinding = (ITypeBinding) binding;
+ return (ASTNode) this.bindingsToAstNodes.get(typeBinding.getTypeDeclaration());
+ } else if (binding instanceof IVariableBinding) {
+ IVariableBinding variableBinding = (IVariableBinding) binding;
+ return (ASTNode) this.bindingsToAstNodes.get(variableBinding.getVariableDeclaration());
+ }
+ return (ASTNode) this.bindingsToAstNodes.get(binding);
+ }
+
+ synchronized ASTNode findDeclaringNode(String bindingKey) {
+ if (bindingKey == null) {
+ return null;
+ }
+ Object binding = this.bindingTables.bindingKeysToBindings.get(bindingKey);
+ if (binding == null)
+ return null;
+ return (ASTNode) this.bindingsToAstNodes.get(binding);
+ }
+
+ IBinding getBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.Binding binding) {
+ switch (binding.kind()) {
+ case Binding.PACKAGE:
+ return getPackageBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) binding);
+ case Binding.TYPE:
+ case Binding.BASE_TYPE:
+ return getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) binding);
+ case Binding.ARRAY_TYPE:
+ return new TypeBinding(this, (org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) binding);
+ case Binding.METHOD:
+ return getMethodBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding) binding);
+ case Binding.FIELD:
+ case Binding.LOCAL:
+ return getVariableBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding) binding);
+ }
+ return null;
+ }
+
+ synchronized org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+ return (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IFunctionBinding getMethodBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding) {
+ if (methodBinding != null && !methodBinding.isValidBinding()) {
+ org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemMethodBinding problemMethodBinding =
+ (org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemMethodBinding) methodBinding;
+ methodBinding = problemMethodBinding.closestMatch;
+ }
+
+ if (methodBinding != null) {
+ IFunctionBinding binding = (IFunctionBinding) this.bindingTables.compilerBindingsToASTBindings.get(methodBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new FunctionBinding(this, methodBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(methodBinding, binding);
+ return binding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IPackageBinding getPackageBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding packageBinding) {
+ if (packageBinding == null || !packageBinding.isValidBinding()) {
+ return null;
+ }
+ IPackageBinding binding = (IPackageBinding) this.bindingTables.compilerBindingsToASTBindings.get(packageBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new PackageBinding(packageBinding, this);
+ this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
+ return binding;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given variable declaration.
+ * This is used for recovered binding only.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param variableDeclaration the given variable declaration
+ * @return the new type binding
+ */
+ synchronized ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableDeclaration);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new RecoveredTypeBinding(this, variableDeclaration);
+ this.bindingTables.compilerBindingsToASTBindings.put(variableDeclaration, binding);
+ return binding;
+ }
+
+ /**
+ * Returns the new type binding corresponding to the given type.
+ * This is used for recovered binding only.
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param type the given type
+ * @return the new type binding
+ */
+ synchronized ITypeBinding getTypeBinding(Type type) {
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(type);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new RecoveredTypeBinding(this, type);
+ this.bindingTables.compilerBindingsToASTBindings.put(type, binding);
+ return binding;
+ }
+
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding getTypeBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+ if (referenceBinding == null) {
+ return null;
+ } else if (!referenceBinding.isValidBinding()) {
+ switch(referenceBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ if (referenceBinding instanceof ProblemReferenceBinding) {
+ ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) referenceBinding;
+ ReferenceBinding binding2 = problemReferenceBinding.closestMatch();
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(binding2);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new TypeBinding(this, binding2);
+ this.bindingTables.compilerBindingsToASTBindings.put(binding2, binding);
+ return binding;
+ }
+ break;
+ case ProblemReasons.NotFound :
+ if (this.isRecoveredBinding) {
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new RecoveredTypeBinding(this, referenceBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+ return binding;
+ }
+ }
+ return null;
+ } else {
+ ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+ if (binding != null) {
+ return binding;
+ }
+ if (referenceBinding instanceof CompilationUnitBinding)
+ binding = new org.eclipse.wst.jsdt.core.dom.JavaScriptUnitBinding(this, referenceBinding);
+ else
+ binding = new TypeBinding(this, referenceBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+ return binding;
+ }
+ }
+
+ synchronized ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
+ if (recoveredTypeBinding== null) {
+ return null;
+ }
+ return new RecoveredTypeBinding(this, recoveredTypeBinding, dimensions);
+ }
+
+ synchronized IVariableBinding getVariableBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding variableBinding, VariableDeclaration variableDeclaration) {
+ if (this.isRecoveredBinding) {
+ if (variableBinding != null) {
+ if (variableBinding.isValidBinding()) {
+ IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+ if (binding != null) {
+ return binding;
+ }
+ if (variableBinding.type != null) {
+ binding = new VariableBinding(this, variableBinding);
+ } else {
+ binding = new RecoveredVariableBinding(this, variableDeclaration);
+ }
+ this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+ return binding;
+ } else {
+ /*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+ */
+ if (variableBinding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+ if (exactBinding != null) {
+ IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding2 != null) {
+ return variableBinding2;
+ }
+ variableBinding2 = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+ return variableBinding2;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ return this.getVariableBinding(variableBinding);
+ }
+
+ public WorkingCopyOwner getWorkingCopyOwner() {
+ return this.workingCopyOwner;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IVariableBinding getVariableBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding variableBinding) {
+ if (variableBinding != null) {
+ if (variableBinding.isValidBinding()) {
+ if (variableBinding.type != null) {
+ IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+ if (binding != null) {
+ return binding;
+ }
+ binding = new VariableBinding(this, variableBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+ return binding;
+ }
+ } else {
+ /*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+ */
+ if (variableBinding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+ if (exactBinding != null) {
+ IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding2 != null) {
+ return variableBinding2;
+ }
+ variableBinding2 = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+ return variableBinding2;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(FunctionInvocation methodInvocation) {
+ Object oldNode = this.newAstToOldAst.get(methodInvocation);
+ if (oldNode instanceof MessageSend) {
+// MessageSend messageSend = (MessageSend) oldNode;
+// org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
+// if (methodBinding instanceof ParameterizedGenericMethodBinding) {
+// ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
+// return genericMethodBinding.inferredReturnType;
+// }
+ }
+ return false;
+ }
+
+ boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation superMethodInvocation) {
+ Object oldNode = this.newAstToOldAst.get(superMethodInvocation);
+ if (oldNode instanceof MessageSend) {
+// MessageSend messageSend = (MessageSend) oldNode;
+// org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
+// if (methodBinding instanceof ParameterizedGenericMethodBinding) {
+// ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
+// return genericMethodBinding.inferredReturnType;
+// }
+ }
+ return false;
+ }
+
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ LookupEnvironment lookupEnvironment() {
+ return this.scope.environment();
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
+ */
+ synchronized void recordScope(ASTNode astNode, BlockScope blockScope) {
+ this.astNodesToBlockScope.put(astNode, blockScope);
+ }
+
+ /*
+ * @see BindingResolver#resolveBoxing(Expression)
+ */
+ boolean resolveBoxing(Expression expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node != null && (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Expression)) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) node;
+ return (compilerExpression.implicitConversion & TypeIds.BOXING) != 0;
+ }
+ return false;
+ }
+
+ /*
+ * @see BindingResolver#resolveUnboxing(Expression)
+ */
+ boolean resolveUnboxing(Expression expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node != null && (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Expression)) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) node;
+ return (compilerExpression.implicitConversion & TypeIds.UNBOXING) != 0;
+ }
+ return false;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstantExpressionValue(Expression)
+ */
+ Object resolveConstantExpressionValue(Expression expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node != null && (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Expression)) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression compilerExpression = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) node;
+ Constant constant = compilerExpression.constant;
+ if (constant != null && constant != Constant.NotAConstant) {
+ switch (constant.typeID()) {
+ case TypeIds.T_int : return new Integer(constant.intValue());
+ case TypeIds.T_short : return new Short(constant.shortValue());
+ case TypeIds.T_char : return new Character(constant.charValue());
+ case TypeIds.T_float : return new Float(constant.floatValue());
+ case TypeIds.T_double : return new Double(constant.doubleValue());
+ case TypeIds.T_boolean : return constant.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+ case TypeIds.T_long : return new Long(constant.longValue());
+ case TypeIds.T_JavaLangString : return constant.stringValue();
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
+ */
+ synchronized IFunctionBinding resolveConstructor(ClassInstanceCreation expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node != null && (node.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) node;
+ return this.getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
+ } else if (node instanceof AllocationExpression) {
+ return this.getMethodBinding(((AllocationExpression)node).binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstructor(ConstructorInvocation)
+ */
+ synchronized IFunctionBinding resolveConstructor(ConstructorInvocation expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof ExplicitConstructorCall) {
+ ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+ return this.getMethodBinding(explicitConstructorCall.binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
+ */
+ synchronized IFunctionBinding resolveConstructor(SuperConstructorInvocation expression) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (node instanceof ExplicitConstructorCall) {
+ ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+ return this.getMethodBinding(explicitConstructorCall.binding);
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveExpressionType(Expression expression) {
+ try {
+ switch(expression.getNodeType()) {
+ case ASTNode.CLASS_INSTANCE_CREATION :
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode astNode = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+ if (astNode instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+ // anonymous type case
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) astNode;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding != null) {
+ return typeBinding;
+ }
+ } else {
+ // should be an AllocationExpression
+ AllocationExpression allocationExpression = (AllocationExpression) astNode;
+ return this.getTypeBinding(allocationExpression.resolvedType);
+ }
+ break;
+ case ASTNode.SIMPLE_NAME :
+ case ASTNode.QUALIFIED_NAME :
+ return this.resolveTypeBindingForName((Name) expression);
+ case ASTNode.ARRAY_INITIALIZER :
+ case ASTNode.ARRAY_CREATION :
+ case ASTNode.ASSIGNMENT :
+ case ASTNode.POSTFIX_EXPRESSION :
+ case ASTNode.PREFIX_EXPRESSION :
+ case ASTNode.TYPE_LITERAL :
+ case ASTNode.INFIX_EXPRESSION :
+ case ASTNode.INSTANCEOF_EXPRESSION :
+ case ASTNode.FIELD_ACCESS :
+ case ASTNode.SUPER_FIELD_ACCESS :
+ case ASTNode.ARRAY_ACCESS :
+ case ASTNode.FUNCTION_INVOCATION :
+ case ASTNode.SUPER_METHOD_INVOCATION :
+ case ASTNode.CONDITIONAL_EXPRESSION :
+ case ASTNode.STRING_LITERAL :
+ if (this.scope != null) {
+ return this.getTypeBinding(this.scope.getJavaLangString());
+ }
+ break;
+ case ASTNode.BOOLEAN_LITERAL :
+ case ASTNode.NULL_LITERAL :
+ case ASTNode.UNDEFINED_LITERAL :
+ case ASTNode.CHARACTER_LITERAL :
+ case ASTNode.REGULAR_EXPRESSION_LITERAL :
+ case ASTNode.NUMBER_LITERAL :
+ Literal literal = (Literal) this.newAstToOldAst.get(expression);
+ return this.getTypeBinding(literal.literalType(this.scope));
+ case ASTNode.THIS_EXPRESSION :
+ ThisReference thisReference = (ThisReference) this.newAstToOldAst.get(expression);
+ BlockScope blockScope = (BlockScope) this.astNodesToBlockScope.get(expression);
+ if (blockScope != null) {
+ return this.getTypeBinding(thisReference.resolveType(blockScope));
+ }
+ break;
+ case ASTNode.PARENTHESIZED_EXPRESSION :
+ ParenthesizedExpression parenthesizedExpression = (ParenthesizedExpression) expression;
+ return this.resolveExpressionType(parenthesizedExpression.getExpression());
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+ VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expression;
+ Type type = variableDeclarationExpression.getType();
+ if (type != null) {
+ return type.resolveBinding();
+ }
+ break;
+ }
+ } catch (AbortCompilation e) {
+ // handle missing types
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveField(FieldAccess)
+ */
+ synchronized IVariableBinding resolveField(FieldAccess fieldAccess) {
+ Object oldNode = this.newAstToOldAst.get(fieldAccess);
+ if (oldNode instanceof FieldReference) {
+ FieldReference fieldReference = (FieldReference) oldNode;
+ return this.getVariableBinding(fieldReference.binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveField(SuperFieldAccess)
+ */
+ synchronized IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+ Object oldNode = this.newAstToOldAst.get(fieldAccess);
+ if (oldNode instanceof FieldReference) {
+ FieldReference fieldReference = (FieldReference) oldNode;
+ return this.getVariableBinding(fieldReference.binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveImport(ImportDeclaration)
+ */
+ synchronized IBinding resolveImport(ImportDeclaration importDeclaration) {
+ if (this.scope == null) return null;
+ try {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(importDeclaration);
+ if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ if ((importReference.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OnDemand) != 0) {
+ Binding binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length), true);
+ if (binding != null) {
+ if ((binding.kind() & Binding.PACKAGE) != 0) {
+ IPackageBinding packageBinding = this.getPackageBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) binding);
+ if (packageBinding == null) {
+ return null;
+ }
+ return packageBinding;
+ } else {
+ // if it is not a package, it has to be a type
+ ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ return typeBinding;
+ }
+ }
+ } else {
+ Binding binding = this.scope.getImport(importReference.tokens, false);
+ if (binding != null) {
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ ITypeBinding typeBinding = this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) binding);
+ return typeBinding == null ? null : typeBinding;
+ }
+ }
+ }
+ }
+ } catch(AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IFunctionBinding resolveMethod(FunctionDeclaration method) {
+ Object oldNode = this.newAstToOldAst.get(method);
+ if (oldNode instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+ IFunctionBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+ if (methodBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(methodBinding, method);
+ String key = methodBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
+ }
+ return methodBinding;
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IFunctionBinding resolveMethod(FunctionInvocation method) {
+ Object oldNode = this.newAstToOldAst.get(method);
+ if (oldNode instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) oldNode;
+ return this.getMethodBinding(messageSend.binding);
+ }
+ return null;
+ }
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IFunctionBinding resolveMethod(SuperMethodInvocation method) {
+ Object oldNode = this.newAstToOldAst.get(method);
+ if (oldNode instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) oldNode;
+ return this.getMethodBinding(messageSend.binding);
+ }
+ return null;
+ }
+
+ synchronized ITypeBinding resolveTypeBindingForName(Name name) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+ int index = name.index;
+ if (node instanceof QualifiedNameReference) {
+ QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+ final char[][] tokens = qualifiedNameReference.tokens;
+ if (tokens.length == index) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ }
+ int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+ if (index < indexOfFirstFieldBinding) {
+ // an extra lookup is required
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) {
+ return null;
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)binding);
+ }
+ } else if (index == indexOfFirstFieldBinding) {
+ if (qualifiedNameReference.isTypeReference()) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ } else {
+ // in this case we want to get the next field declaring's class
+ if (qualifiedNameReference.otherBindings == null) {
+ return null;
+ }
+ FieldBinding fieldBinding = qualifiedNameReference.otherBindings[0];
+ if (fieldBinding == null) return null;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
+ if (type == null) { // array length scenario
+ // use type from first binding (no capture needed for array type)
+ switch (qualifiedNameReference.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.RestrictiveFlagMASK) {
+ case Binding.FIELD:
+ type = ((FieldBinding) qualifiedNameReference.binding).type;
+ break;
+ case Binding.LOCAL:
+ type = ((LocalVariableBinding) qualifiedNameReference.binding).type;
+ break;
+ }
+ }
+ return this.getTypeBinding(type);
+ }
+ } else {
+ /* This is the case for a name which is part of a qualified name that
+ * cannot be resolved. See PR 13063.
+ */
+ if (qualifiedNameReference.otherBindings == null) return null;
+ final int otherBindingsLength = qualifiedNameReference.otherBindings.length;
+ if (otherBindingsLength == (index - indexOfFirstFieldBinding)) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ }
+ FieldBinding fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding];
+ if (fieldBinding == null) return null;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
+ if (type == null) { // array length scenario
+ // use type from previous binding (no capture needed for array type)
+ fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1];
+ if (fieldBinding == null) return null;
+ type = fieldBinding.type;
+ }
+ return this.getTypeBinding(type);
+ }
+ } else if (node instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+ if (qualifiedTypeReference.resolvedType == null) {
+ return null;
+ }
+ if (index == qualifiedTypeReference.tokens.length) {
+ if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+ if (typeRef.packageBinding != null) {
+ return null;
+ }
+ }
+ return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+ } else {
+ if (index >= 0) {
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) {
+ return null;
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)binding);
+ } else {
+ return null;
+ }
+ }
+ }
+ } else if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ int importReferenceLength = importReference.tokens.length;
+ if (index >= 0) {
+ Binding binding = null;
+ if (this.scope == null) return null;
+ if (importReferenceLength == index) {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OnDemand) != 0);
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ } else {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true);
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ }
+ if (binding != null) {
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)binding);
+ }
+ return null;
+ }
+ }
+ } else if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ IFunctionBinding method = this.getMethodBinding(methodDeclaration.binding);
+ if (method == null) return null;
+ return method.getReturnType();
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding != null) {
+ return typeBinding;
+ }
+ } if (node instanceof JavadocSingleNameReference) {
+ JavadocSingleNameReference singleNameReference = (JavadocSingleNameReference) node;
+ LocalVariableBinding localVariable = (LocalVariableBinding)singleNameReference.binding;
+ if (localVariable != null) {
+ return this.getTypeBinding(localVariable.type);
+ }
+ } if (node instanceof SingleNameReference) {
+ SingleNameReference singleNameReference = (SingleNameReference) node;
+ return this.getTypeBinding(singleNameReference.resolvedType);
+ } else if (node instanceof LocalDeclaration) {
+ IVariableBinding variable = this.getVariableBinding(((LocalDeclaration)node).binding);
+ if (variable == null) return null;
+ return variable.getType();
+ } else if (node instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+ if (fieldRef.methodBinding != null) {
+ return getMethodBinding(fieldRef.methodBinding).getReturnType();
+ }
+ return getTypeBinding(fieldRef.resolvedType);
+ } else if (node instanceof FieldReference) {
+ return getTypeBinding(((FieldReference) node).resolvedType);
+ } else if (node instanceof SingleTypeReference) {
+ SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+ if (binding != null) {
+ return this.getTypeBinding(binding.leafComponentType());
+ }
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) node;
+ IVariableBinding field = this.getVariableBinding(fieldDeclaration.binding);
+ if (field == null) return null;
+ return field.getType();
+ } else if (node instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) node;
+ IFunctionBinding method = getMethodBinding(messageSend.binding);
+ if (method == null) return null;
+ return method.getReturnType();
+ } else if (node instanceof AllocationExpression) {
+ AllocationExpression allocation = (AllocationExpression) node;
+ return getTypeBinding(allocation.resolvedType);
+ } else if (node instanceof JavadocImplicitTypeReference) {
+ JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
+ return getTypeBinding(implicitRef.resolvedType);
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IBinding resolveName(Name name) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+ int index = name.index;
+ if (node instanceof QualifiedNameReference) {
+ QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+ final char[][] tokens = qualifiedNameReference.tokens;
+ int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+ if (index < indexOfFirstFieldBinding) {
+ // an extra lookup is required
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) {
+ return this.getPackageBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding)binding);
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)binding);
+ }
+ } else if (index == indexOfFirstFieldBinding) {
+ if (qualifiedNameReference.isTypeReference()) {
+ return this.getTypeBinding(qualifiedNameReference.resolvedType);
+ } else {
+ Binding binding = qualifiedNameReference.binding;
+ if (binding != null) {
+ if (binding.isValidBinding()) {
+ return this.getVariableBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding) binding);
+ } else if (binding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ if (declaringClass != null) {
+ FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
+ if (exactBinding != null) {
+ if (exactBinding.type != null) {
+ IVariableBinding variableBinding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding != null) {
+ return variableBinding;
+ }
+ variableBinding = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding);
+ return variableBinding;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ /* This is the case for a name which is part of a qualified name that
+ * cannot be resolved. See PR 13063.
+ */
+ if (qualifiedNameReference.otherBindings == null || (index - indexOfFirstFieldBinding - 1) < 0) {
+ return null;
+ } else {
+ return this.getVariableBinding(qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1]);
+ }
+ }
+ } else if (node instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+ if (qualifiedTypeReference.resolvedType == null) {
+ return null;
+ }
+ if (index == qualifiedTypeReference.tokens.length) {
+ if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+ if (typeRef.packageBinding != null) {
+ return getPackageBinding(typeRef.packageBinding);
+ }
+ }
+ return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+ } else {
+ if (index >= 0) {
+ BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+ Binding binding = null;
+ try {
+ if (internalScope == null) {
+ if (this.scope == null) return null;
+ binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ } else {
+ binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) {
+ return this.getPackageBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding)binding);
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)binding);
+ } else {
+ return null;
+ }
+ }
+ }
+ } else if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ int importReferenceLength = importReference.tokens.length;
+ if (index >= 0) {
+ Binding binding = null;
+ if (this.scope == null) return null;
+ if (importReferenceLength == index) {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.OnDemand) != 0);
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ } else {
+ try {
+ binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true);
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ }
+ }
+ if (binding != null) {
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) {
+ return this.getPackageBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding)binding);
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) {
+ // it is a type
+ return this.getTypeBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)binding);
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding) {
+ // it is a type
+ return this.getVariableBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding)binding);
+ } else if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding) {
+ // it is a type
+ return this.getMethodBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding)binding);
+ } else {
+ return null;
+ }
+ }
+ }
+ } else if (node instanceof CompilationUnitDeclaration) {
+ CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) node;
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types == null || types.length == 0) {
+ return null;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration type = types[0];
+ if (type != null) {
+ ITypeBinding typeBinding = this.getTypeBinding(type.binding);
+ if (typeBinding != null) {
+ return typeBinding.getPackage();
+ }
+ }
+ } else if (node instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+ IFunctionBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+ if (methodBinding != null) {
+ return methodBinding;
+ }
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding != null) {
+ return typeBinding;
+ }
+ } if (node instanceof SingleNameReference) {
+ SingleNameReference singleNameReference = (SingleNameReference) node;
+ if (singleNameReference.isTypeReference()) {
+ return this.getTypeBinding(singleNameReference.resolvedType);
+ } else {
+ // this is a variable or a field
+ Binding binding = singleNameReference.binding;
+ if (binding != null) {
+ if (binding.isValidBinding()) {
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding)
+ return this.getVariableBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding) binding);
+ if (binding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding)
+ return this.getMethodBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding) binding);
+ } else {
+ /*
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+ */
+ if (binding instanceof ProblemFieldBinding) {
+ ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+ switch(problemFieldBinding.problemId()) {
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+ FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+ if (exactBinding != null) {
+ if (exactBinding.type != null) {
+ IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+ if (variableBinding2 != null) {
+ return variableBinding2;
+ }
+ variableBinding2 = new VariableBinding(this, exactBinding);
+ this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+ return variableBinding2;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else if (node instanceof LocalDeclaration) {
+ return this.getVariableBinding(((LocalDeclaration)node).binding);
+ } else if (node instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+ if (fieldRef.methodBinding != null) {
+ return getMethodBinding(fieldRef.methodBinding);
+ }
+ return getVariableBinding(fieldRef.binding);
+ } else if (node instanceof FieldReference) {
+ return getVariableBinding(((FieldReference) node).binding);
+ } else if (node instanceof SingleTypeReference) {
+ SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+ if (binding != null) {
+ if (!binding.isValidBinding() && node instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) node;
+ if (typeRef.packageBinding != null) {
+ return getPackageBinding(typeRef.packageBinding);
+ }
+ }
+ return this.getTypeBinding(binding.leafComponentType());
+ }
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) node;
+ return this.getVariableBinding(fieldDeclaration.binding);
+ } else if (node instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) node;
+ return getMethodBinding(messageSend.binding);
+ } else if (node instanceof AllocationExpression) {
+ AllocationExpression allocation = (AllocationExpression) node;
+ return getMethodBinding(allocation.binding);
+ } else if (node instanceof JavadocImplicitTypeReference) {
+ JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
+ return getTypeBinding(implicitRef.resolvedType);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolvePackage(PackageDeclaration)
+ */
+ synchronized IPackageBinding resolvePackage(PackageDeclaration pkg) {
+ if (this.scope == null) return null;
+ try {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(pkg);
+ if (node instanceof ImportReference) {
+ ImportReference importReference = (ImportReference) node;
+ Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
+ if ((binding != null) && (binding.isValidBinding())) {
+ IPackageBinding packageBinding = this.getPackageBinding((org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding) binding);
+ if (packageBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(packageBinding, pkg);
+ String key = packageBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, packageBinding);
+ }
+ return packageBinding;
+ }
+ }
+ } catch (AbortCompilation e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see BindingResolver#resolveReference(MemberRef)
+ *
+ */
+ synchronized IBinding resolveReference(MemberRef ref) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+ if (expression instanceof TypeReference) {
+ return getTypeBinding(expression.resolvedType);
+ }
+ else if (expression instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) expression;
+ if (fieldRef.methodBinding != null) {
+ return getMethodBinding(fieldRef.methodBinding);
+ }
+ return getVariableBinding(fieldRef.binding);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see BindingResolver#resolveReference(FunctionRef)
+ *
+ */
+ synchronized IBinding resolveReference(FunctionRef ref) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.Expression expression = (org.eclipse.wst.jsdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+ if (expression instanceof JavadocMessageSend) {
+ return this.getMethodBinding(((JavadocMessageSend)expression).binding);
+ }
+ else if (expression instanceof JavadocAllocationExpression) {
+ return this.getMethodBinding(((JavadocAllocationExpression)expression).binding);
+ }
+ return null;
+ }
+
+ /*
+ * @see BindingResolver#resolveType(AnonymousClassDeclaration)
+ */
+ synchronized ITypeBinding resolveType(AnonymousClassDeclaration type) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+ if (node != null && (node.bits & org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(anonymousLocalTypeDeclaration.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, type);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveType(Type type) {
+ // retrieve the old ast node
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = (org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding = null;
+ if (node != null) {
+ if (node instanceof TypeReference) {
+ TypeReference typeReference = (TypeReference) node;
+ binding = typeReference.resolvedType;
+ } else if (node instanceof SingleNameReference && ((SingleNameReference)node).isTypeReference()) {
+ binding = (((SingleNameReference)node).resolvedType);
+ } else if (node instanceof QualifiedNameReference && ((QualifiedNameReference)node).isTypeReference()) {
+ binding = (((QualifiedNameReference)node).resolvedType);
+ } else if (node instanceof ArrayAllocationExpression) {
+ binding = ((ArrayAllocationExpression) node).resolvedType;
+ }
+ if (binding != null) {
+ if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ if (this.scope == null) return null;
+ if (binding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
+ } else {
+ return getTypeBinding(this.scope.createArrayType(binding, arrayType.getDimensions()));
+ }
+ } else {
+ if (binding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return getTypeBinding(arrayBinding.leafComponentType);
+ } else {
+ return getTypeBinding(binding);
+ }
+ }
+ }
+ } else if (type.isPrimitiveType()) {
+ /* Handle the void primitive type returned by getReturnType for a method declaration
+ * that is a constructor declaration. It prevents null from being returned
+ */
+ if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
+ return this.getTypeBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.VOID);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveType(TypeDeclaration type) {
+ final Object node = this.newAstToOldAst.get(type);
+ if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, type);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ ITypeBinding resolveType(JavaScriptUnit compilationUnit) {
+ final Object node = this.newAstToOldAst.get(compilationUnit);
+ if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration =
+ (org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration) node;
+ ITypeBinding typeBinding = this.getTypeBinding(compilationUnitDeclaration.compilationUnitBinding);
+ if (typeBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(typeBinding, compilationUnit);
+ String key = typeBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+ }
+ return typeBinding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized IVariableBinding resolveVariable(VariableDeclaration variable) {
+ final Object node = this.newAstToOldAst.get(variable);
+ if (node instanceof AbstractVariableDeclaration) {
+ AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
+ if (abstractVariableDeclaration instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
+ IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding, variable);
+ if (variableBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(variableBinding, variable);
+ String key = variableBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+ }
+ return variableBinding;
+ }
+ IVariableBinding variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding, variable);
+ if (variableBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(variableBinding, variable);
+ String key = variableBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+ }
+ return variableBinding;
+ }
+ return null;
+ }
+
+ synchronized IVariableBinding resolveVariable(VariableDeclarationStatement variable) {
+ final Object node = this.newAstToOldAst.get(variable);
+ if (node instanceof AbstractVariableDeclaration) {
+ AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
+ if (abstractVariableDeclaration instanceof org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
+ IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
+ if (variableBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(variableBinding, variable);
+ String key = variableBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+ }
+ return variableBinding;
+ }
+ IVariableBinding variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding);
+ if (variableBinding == null) {
+ return null;
+ }
+ this.bindingsToAstNodes.put(variableBinding, variable);
+ String key = variableBinding.getKey();
+ if (key != null) {
+ this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+ }
+ return variableBinding;
+ }
+ return null;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized ITypeBinding resolveWellKnownType(String name) {
+ if (this.scope == null) return null;
+ try {
+// if (("boolean".equals(name))//$NON-NLS-1$
+// || ("char".equals(name))//$NON-NLS-1$
+// || ("byte".equals(name))//$NON-NLS-1$
+// || ("short".equals(name))//$NON-NLS-1$
+// || ("int".equals(name))//$NON-NLS-1$
+// || ("long".equals(name))//$NON-NLS-1$
+// || ("float".equals(name))//$NON-NLS-1$
+// || ("double".equals(name))//$NON-NLS-1$
+// || ("void".equals(name))) {//$NON-NLS-1$
+// return this.getTypeBinding(Scope.getBaseType(name.toCharArray()));
+// } else
+ if ("Object".equals(name)) {//$NON-NLS-1$
+ return this.getTypeBinding(this.scope.getJavaLangObject());
+ } else if ("String".equals(name)) {//$NON-NLS-1$
+ return this.getTypeBinding(this.scope.getJavaLangString());
+ } else if ("Number".equals(name)) {//$NON-NLS-1$
+ return this.getTypeBinding(this.scope.getJavaLangNumber());
+ } else if ("Function".equals(name)) {//$NON-NLS-1$
+ return this.getTypeBinding(this.scope.getJavaLangFunction());
+ } else if ("Boolean".equals(name)) {//$NON-NLS-1$
+ return this.getTypeBinding(this.scope.getJavaLangBoolean());
+// } else if ("java.lang.StringBuffer".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_STRINGBUFFER, 3));
+// } else if ("java.lang.Throwable".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getJavaLangThrowable());
+// } else if ("java.lang.Exception".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_EXCEPTION, 3));
+// } else if ("java.lang.RuntimeException".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3));
+// } else if ("java.lang.Error".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_ERROR, 3));
+// } else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getJavaLangClass());
+// } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getJavaLangCloneable());
+// } else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getJavaIoSerializable());
+// } else if ("java.lang.Boolean".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BOOLEAN, 3));
+// } else if ("java.lang.Byte".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BYTE, 3));
+// } else if ("java.lang.Character".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_CHARACTER, 3));
+// } else if ("java.lang.Double".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_DOUBLE, 3));
+// } else if ("java.lang.Float".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_FLOAT, 3));
+// } else if ("java.lang.Integer".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_INTEGER, 3));
+// } else if ("java.lang.Long".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_LONG, 3));
+// } else if ("java.lang.Short".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_SHORT, 3));
+// } else if ("java.lang.Void".equals(name)) {//$NON-NLS-1$
+// return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_VOID, 3));
+ }
+ } catch (AbortCompilation e) {
+ // ignore missing types
+ }
+ return null;
+ }
+
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ public CompilationUnitScope scope() {
+ return this.scope;
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized void store(ASTNode node, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode oldASTNode) {
+ this.newAstToOldAst.put(node, oldASTNode);
+ }
+
+ /*
+ * Method declared on BindingResolver.
+ */
+ synchronized void updateKey(ASTNode node, ASTNode newNode) {
+ Object astNode = this.newAstToOldAst.remove(node);
+ if (astNode != null) {
+ this.newAstToOldAst.put(newNode, astNode);
+ }
+ }
+
+ /**
+ * Answer an array type binding with the given type binding and the given
+ * dimensions.
+ *
+ * If the given type binding is an array binding, then the resulting dimensions is the given dimensions
+ * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
+ * dimensions.
+ *
+ *
+ * The default implementation of this method returns null
.
+ * Subclasses may reimplement.
+ *
+ *
+ * @param typeBinding the given type binding
+ * @param dimensions the given dimensions
+ * @return an array type binding with the given type binding and the given
+ * dimensions
+ * @throws IllegalArgumentException if the type binding represents the void
type binding
+ */
+ ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
+ if (typeBinding.isRecovered()) throw new IllegalArgumentException("Cannot be called on a recovered type binding"); //$NON-NLS-1$
+ ITypeBinding leafComponentType = typeBinding;
+ int actualDimensions = dimensions;
+ if (typeBinding.isArray()) {
+ leafComponentType = typeBinding.getElementType();
+ actualDimensions += typeBinding.getDimensions();
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding leafTypeBinding = null;
+ if (leafComponentType.isPrimitive()) {
+ String name = leafComponentType.getBinaryName();
+ switch(name.charAt(0)) {
+ case 'I' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.INT;
+ break;
+ case 'Z' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.BOOLEAN;
+ break;
+ case 'C' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.CHAR;
+ break;
+ case 'J' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.LONG;
+ break;
+ case 'S' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.SHORT;
+ break;
+ case 'D' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.DOUBLE;
+ break;
+ case 'F' :
+ leafTypeBinding = org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.FLOAT;
+ break;
+ case 'V' :
+ throw new IllegalArgumentException();
+ }
+ } else {
+ leafTypeBinding = ((TypeBinding) leafComponentType).binding;
+ }
+ if (!(leafComponentType instanceof TypeBinding)) return null;
+ return this.getTypeBinding(this.lookupEnvironment().createArrayType(leafTypeBinding, actualDimensions));
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultCommentMapper.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultCommentMapper.java
new file mode 100644
index 0000000..7979c26
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DefaultCommentMapper.java
@@ -0,0 +1,650 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+/**
+ * Internal class for associating comments with AST nodes.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+class DefaultCommentMapper {
+ Comment[] comments;
+ Scanner scanner;
+
+ // extended nodes storage
+ int leadingPtr;
+ ASTNode[] leadingNodes;
+ long[] leadingIndexes;
+ int trailingPtr, lastTrailingPtr;
+ ASTNode[] trailingNodes;
+ long[] trailingIndexes;
+ static final int STORAGE_INCREMENT = 16;
+
+ /**
+ * @param table the given table of comments
+ */
+ DefaultCommentMapper(Comment[] table) {
+ this.comments = table;
+ }
+
+ boolean hasSameTable(Comment[] table) {
+ return this.comments == table;
+ }
+
+ /**
+ * Get comment of the list which includes a given position
+ *
+ * @param position The position belonging to the looked up comment
+ * @return comment which includes the given position or null if none was found
+ */
+ Comment getComment(int position) {
+
+ if (this.comments == null) {
+ return null;
+ }
+ int size = this.comments.length;
+ if (size == 0) {
+ return null;
+ }
+ int index = getCommentIndex(0, position, 0);
+ if (index<0) {
+ return null;
+ }
+ return this.comments[index];
+ }
+
+ /*
+ * Get the index of comment which contains given position.
+ * If there's no matching comment, then return depends on exact parameter:
+ * = 0: return -1
+ * < 0: return index of the comment before the given position
+ * > 0: return index of the comment after the given position
+ */
+ private int getCommentIndex(int start, int position, int exact) {
+ if (position == 0) {
+ if (this.comments.length > 0 && this.comments[0].getStartPosition() == 0) {
+ return 0;
+ }
+ return -1;
+ }
+ int bottom = start, top = this.comments.length - 1;
+ int i = 0, index = -1;
+ Comment comment = null;
+ while (bottom <= top) {
+ i = bottom + (top - bottom) /2;
+ comment = this.comments[i];
+ int commentStart = comment.getStartPosition();
+ if (position < commentStart) {
+ top = i-1;
+ } else if (position >=(commentStart+comment.getLength())) {
+ bottom = i+1;
+ } else {
+ index = i;
+ break;
+ }
+ }
+ if (index<0 && exact!=0) {
+ comment = this.comments[i];
+ if (position < comment.getStartPosition()) {
+ return exact<0 ? i-1 : i;
+ } else {
+ return exact<0 ? i : i+1;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Returns the extended start position of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return the 0-based character index, or -1
+ * if no source position information is recorded for this node
+ * @see #getExtendedLength(ASTNode)
+ *
+ */
+ public int getExtendedStartPosition(ASTNode node) {
+ if (this.leadingPtr >= 0) {
+ long range = -1;
+ for (int i=0; range<0 && i<=this.leadingPtr; i++) {
+ if (this.leadingNodes[i] == node) range = this.leadingIndexes[i];
+ }
+ if (range >= 0) {
+ return this.comments[(int)(range>>32)].getStartPosition() ;
+ }
+ }
+ return node.getStartPosition();
+ }
+
+ /*
+ * Search the line number corresponding to a specific position
+ * between the given line range (inclusive)
+ * @param position int
+ * @parem lineRange size-2 int[]
+ * @return int
+ */
+ public final int getLineNumber(int position, int[] lineRange) {
+ int[] lineEnds = this.scanner.lineEnds;
+ int length = lineEnds.length;
+ return Util.getLineNumber(position, lineEnds, (lineRange[0] > length ? length : lineRange[0]) -1, (lineRange[1] > length ? length : lineRange[1]) - 1);
+ }
+
+ /*
+ * Returns the extended end position of the given node.
+ */
+ public int getExtendedEnd(ASTNode node) {
+ int end = node.getStartPosition() + node.getLength();
+ if (this.trailingPtr >= 0) {
+ long range = -1;
+ for (int i=0; range<0 && i<=this.trailingPtr; i++) {
+ if (this.trailingNodes[i] == node) range = this.trailingIndexes[i];
+ }
+ if (range >= 0) {
+ Comment lastComment = this.comments[(int) range];
+ end = lastComment.getStartPosition() + lastComment.getLength();
+ }
+ }
+ return end-1;
+ }
+
+ /**
+ * Returns the extended source length of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return a (possibly 0) length, or 0
+ * if no source position information is recorded for this node
+ * @see #getExtendedStartPosition(ASTNode)
+ * @see #getExtendedEnd(ASTNode)
+ *
+ */
+ public int getExtendedLength(ASTNode node) {
+ return getExtendedEnd(node) - getExtendedStartPosition(node) + 1;
+ }
+
+ /**
+ * Return index of first leading comment of a given node.
+ *
+ * @param node
+ * @return index of first leading comment or -1 if node has no leading comment
+ */
+ int firstLeadingCommentIndex(ASTNode node) {
+ if (this.leadingPtr >= 0) {
+ for (int i=0; i<=this.leadingPtr; i++) {
+ if (this.leadingNodes[i] == node) {
+ return (int) (this.leadingIndexes[i]>>32);
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Return index of last trailing comment of a given node.
+ *
+ * @param node
+ * @return index of last trailing comment or -1 if node has no trailing comment
+ */
+ int lastTrailingCommentIndex(ASTNode node) {
+ if (this.trailingPtr >= 0) {
+ for (int i=0; i<=this.trailingPtr; i++) {
+ if (this.trailingNodes[i] == node) {
+ return (int) this.trailingIndexes[i];
+ }
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * Initialize leading and trailing comments tables in whole nodes hierarchy of a compilation
+ * unit.
+ * Scanner is necessary to scan between nodes and comments and verify if there's
+ * nothing else than white spaces.
+ */
+ void initialize(JavaScriptUnit unit, Scanner sc) {
+
+ // Init array pointers
+ this.leadingPtr = -1;
+ this.trailingPtr = -1;
+
+ // Init comments
+ this.comments = unit.optionalCommentTable;
+ if (this.comments == null) {
+ return;
+ }
+ int size = this.comments.length;
+ if (size == 0) {
+ return;
+ }
+
+ // Init scanner and start ranges computing
+ this.scanner = sc;
+ this.scanner.tokenizeWhiteSpace = true;
+
+ // Start unit visit
+ DefaultASTVisitor commentVisitor = new CommentMapperVisitor();
+ unit.accept(commentVisitor);
+
+ // Reduce leading arrays if necessary
+ int leadingCount = this.leadingPtr + 1;
+ if (leadingCount > 0 && leadingCount < this.leadingIndexes.length) {
+ System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[leadingCount], 0, leadingCount);
+ System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes= new long[leadingCount], 0, leadingCount);
+ }
+
+ // Reduce trailing arrays if necessary
+ if (this.trailingPtr >= 0) {
+ // remove last remaining unresolved nodes
+ while (this.trailingIndexes[this.trailingPtr] == -1) {
+ this.trailingPtr--;
+ if (this.trailingPtr < 0) {
+ this.trailingIndexes = null;
+ this.trailingNodes = null;
+ break;
+ }
+ }
+
+ // reduce array size
+ int trailingCount = this.trailingPtr + 1;
+ if (trailingCount > 0 && trailingCount < this.trailingIndexes.length) {
+ System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[trailingCount], 0, trailingCount);
+ System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes= new long[trailingCount], 0, trailingCount);
+ }
+ }
+
+ // Release scanner as it's only used during unit visit
+ this.scanner = null;
+ }
+
+ /**
+ * Search and store node leading comments. Comments are searched in position range
+ * from previous extended position to node start position. If one or several comment are found,
+ * returns first comment start position, otherwise returns node start position.
+ *
+ * Starts to search for first comment before node start position and return if none was found...
+ *
+ * When first comment is found before node, goes up in comment list until one of
+ * following conditions becomes true:
+ *
+ * - comment end is before previous end
+ * - comment start and previous end is on the same line but not on same line of node start
+ * - there's other than white characters between current node and comment
+ * - there's more than 1 line between current node and comment
+ *
+ * If some comment have been found, then no token should be on
+ * on the same line before, so remove all comments which do not verify this assumption.
+ *
+ * If finally there's leading still comments, then stores indexes of the first and last one
+ * in leading comments table.
+ */
+ int storeLeadingComments(ASTNode node, int previousEnd, int[] parentLineRange) {
+ // Init extended position
+ int nodeStart = node.getStartPosition();
+ int extended = nodeStart;
+
+ // Get line of node start position
+ int previousEndLine = getLineNumber(previousEnd, parentLineRange);
+ int nodeStartLine = getLineNumber(nodeStart, parentLineRange);
+
+ // Find first comment index
+ int idx = getCommentIndex(0, nodeStart, -1);
+ if (idx == -1) {
+ return nodeStart;
+ }
+
+ // Look after potential comments
+ int startIdx = -1;
+ int endIdx = idx;
+ int previousStart = nodeStart;
+ while (idx >= 0 && previousStart >= previousEnd) {
+ // Verify for each comment that there's only white spaces between end and start of {following comment|node}
+ Comment comment = this.comments[idx];
+ int commentStart = comment.getStartPosition();
+ int end = commentStart+comment.getLength()-1;
+ int commentLine = getLineNumber(commentStart, parentLineRange);
+ if (end <= previousEnd || (commentLine == previousEndLine && commentLine != nodeStartLine)) {
+ // stop search on condition 1) and 2)
+ break;
+ } else if ((end+1) < previousStart) { // may be equals => then no scan is necessary
+ this.scanner.resetTo(end+1, previousStart);
+ try {
+ int token = this.scanner.getNextToken();
+ if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != previousStart) {
+ // stop search on condition 3)
+ // if first comment fails, then there's no extended position in fact
+ if (idx == endIdx) {
+ return nodeStart;
+ }
+ break;
+ }
+ } catch (InvalidInputException e) {
+ // Should not happen, but return no extended position...
+ return nodeStart;
+ }
+ // verify that there's no more than one line between node/comments
+ char[] gap = this.scanner.getCurrentIdentifierSource();
+ int nbrLine = 0;
+ int pos = -1;
+ while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
+ nbrLine++;
+ }
+ if (nbrLine > 1) {
+ // stop search on condition 4)
+ break;
+ }
+ }
+ // Store previous infos
+ previousStart = commentStart;
+ startIdx = idx--;
+ }
+ if (startIdx != -1) {
+ // Verify that there's no token on the same line before first leading comment
+ int commentStart = this.comments[startIdx].getStartPosition();
+ if (previousEnd < commentStart && previousEndLine != nodeStartLine) {
+ int lastTokenEnd = previousEnd;
+ this.scanner.resetTo(previousEnd, commentStart);
+ try {
+ while (this.scanner.currentPosition < commentStart) {
+ if (this.scanner.getNextToken() != TerminalTokens.TokenNameWHITESPACE) {
+ lastTokenEnd = this.scanner.getCurrentTokenEndPosition();
+ }
+ }
+ } catch (InvalidInputException e) {
+ // do nothing
+ }
+ int lastTokenLine = getLineNumber(lastTokenEnd, parentLineRange);
+ int length = this.comments.length;
+ while (startIdx
+ * Starts to search for first comment after node end position and return if none was found...
+ *
+ * When first comment is found after node, goes down in comment list until one of
+ * following conditions becomes true:
+ *
+ * - comment start is after next start
+ * - there's other than white characters between current node and comment
+ * - there's more than 1 line between current node and comment
+ *
+ * If at least potential comments have been found, then all of them has to be separated
+ * from following node. So, remove all comments which do not verify this assumption.
+ * Note that this verification is not applicable on last node.
+ *
+ * If finally there's still trailing comments, then stores indexes of the first and last one
+ * in trailing comments table.
+ */
+ int storeTrailingComments(ASTNode node, int nextStart, boolean lastChild, int[] parentLineRange) {
+
+ // Init extended position
+ int nodeEnd = node.getStartPosition()+node.getLength()-1;
+ if (nodeEnd == nextStart) {
+ // special case for last child of its parent
+ if (++this.trailingPtr == 0) {
+ this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+ this.trailingIndexes = new long[STORAGE_INCREMENT];
+ this.lastTrailingPtr = -1;
+ } else if (this.trailingPtr == this.trailingNodes.length) {
+ int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
+ System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
+ System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
+ }
+ this.trailingNodes[this.trailingPtr] = node;
+ this.trailingIndexes[this.trailingPtr] = -1;
+ return nodeEnd;
+ }
+ int extended = nodeEnd;
+
+ // Get line number
+ int nodeEndLine = getLineNumber(nodeEnd, parentLineRange);
+
+ // Find comments range index
+ int idx = getCommentIndex(0, nodeEnd, 1);
+ if (idx == -1) {
+ return nodeEnd;
+ }
+
+ // Look after potential comments
+ int startIdx = idx;
+ int endIdx = -1;
+ int length = this.comments.length;
+ int commentStart = extended+1;
+ int previousEnd = nodeEnd+1;
+ int sameLineIdx = -1;
+ while (idx= nextStart) {
+ // stop search on condition 1)
+ break;
+ } else if (previousEnd < commentStart) {
+ this.scanner.resetTo(previousEnd, commentStart);
+ try {
+ int token = this.scanner.getNextToken();
+ if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != commentStart) {
+ // stop search on condition 2)
+ // if first index fails, then there's no extended position in fact...
+ if (idx == startIdx) {
+ return nodeEnd;
+ }
+ // otherwise we get the last index of trailing comment => break
+ break;
+ }
+ } catch (InvalidInputException e) {
+ // Should not happen, but return no extended position...
+ return nodeEnd;
+ }
+ // verify that there's no more than one line between node/comments
+ char[] gap = this.scanner.getCurrentIdentifierSource();
+ int nbrLine = 0;
+ int pos = -1;
+ while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
+ nbrLine++;
+ }
+ if (nbrLine > 1) {
+ // stop search on condition 3)
+ break;
+ }
+ }
+ // Store index if we're on the same line than node end
+ int commentLine = getLineNumber(commentStart, parentLineRange);
+ if (commentLine == nodeEndLine) {
+ sameLineIdx = idx;
+ }
+ // Store previous infos
+ previousEnd = commentStart+comment.getLength();
+ endIdx = idx++;
+ }
+ if (endIdx != -1) {
+ // Verify that following node start is separated
+ if (!lastChild) {
+ int nextLine = getLineNumber(nextStart, parentLineRange);
+ int previousLine = getLineNumber(previousEnd, parentLineRange);
+ if((nextLine - previousLine) <= 1) {
+ if (sameLineIdx == -1) return nodeEnd;
+ endIdx = sameLineIdx;
+ }
+ }
+ // Store trailing comments indexes
+ if (++this.trailingPtr == 0) {
+ this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+ this.trailingIndexes = new long[STORAGE_INCREMENT];
+ this.lastTrailingPtr = -1;
+ } else if (this.trailingPtr == this.trailingNodes.length) {
+ int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
+ System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
+ System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
+ }
+ this.trailingNodes[this.trailingPtr] = node;
+ long nodeRange = (((long)startIdx)<<32) + endIdx;
+ this.trailingIndexes[this.trailingPtr] = nodeRange;
+ // Compute new extended end
+ extended = this.comments[endIdx].getStartPosition()+this.comments[endIdx].getLength()-1;
+ // Look for children unresolved extended end
+ ASTNode previousNode = node;
+ int ptr = this.trailingPtr - 1; // children extended end were stored before
+ while (ptr >= 0) {
+ long range = this.trailingIndexes[ptr];
+ if (range != -1) break; // there's no more unresolved nodes
+ ASTNode unresolved = this.trailingNodes[ptr];
+ if (previousNode != unresolved.getParent()) break; // we're no longer in node ancestor hierarchy
+ this.trailingIndexes[ptr] = nodeRange;
+ previousNode = unresolved;
+ ptr--; // get previous node
+ }
+ // Remove remaining unresolved nodes
+ if (ptr > this.lastTrailingPtr) {
+ int offset = ptr - this.lastTrailingPtr;
+ for (int i=ptr+1; i<=this.trailingPtr; i++) {
+ this.trailingNodes[i-offset] = this.trailingNodes[i];
+ this.trailingIndexes[i-offset] = this.trailingIndexes[i];
+ }
+ this.trailingPtr -= offset;
+ }
+ this.lastTrailingPtr = this.trailingPtr;
+ }
+ return extended;
+ }
+
+ class CommentMapperVisitor extends DefaultASTVisitor {
+
+ ASTNode topSiblingParent = null;
+ ASTNode[] siblings = new ASTNode[10];
+ int[][] parentLineRange = new int[10][];
+ int siblingPtr = -1;
+
+ protected boolean visitNode(ASTNode node) {
+ if (node instanceof InferredType)
+ return true;
+
+ // Get default previous end
+ ASTNode parent = node.getParent();
+ int previousEnd = parent.getStartPosition();
+
+ // Look for sibling node
+ ASTNode sibling = parent == this.topSiblingParent ? (ASTNode) this.siblings[this.siblingPtr] : null;
+ if (sibling != null) {
+ // Found one previous sibling, so compute its trailing comments using current node start position
+ try {
+ previousEnd = storeTrailingComments(sibling, node.getStartPosition(), false, this.parentLineRange[this.siblingPtr]);
+ } catch (Exception ex) {
+ // Give up extended ranges at this level if unexpected exception happens...
+ }
+ }
+
+ // Stop visit for malformed node (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049)
+ if ((node.typeAndFlags & ASTNode.MALFORMED) != 0) {
+ return false;
+ }
+
+ // Compute leading comments for current node
+ int[] previousLineRange = this.siblingPtr > -1 ? this.parentLineRange[this.siblingPtr] : new int[] {1, DefaultCommentMapper.this.scanner.linePtr+1};
+ try {
+ storeLeadingComments(node, previousEnd, previousLineRange);
+ } catch (Exception ex) {
+ // Give up extended ranges at this level if unexpected exception happens...
+ }
+
+ // Store current node as waiting sibling for its parent
+ if (this.topSiblingParent != parent) {
+ if (this.siblings.length == ++this.siblingPtr) {
+ System.arraycopy(this.siblings, 0, this.siblings = new ASTNode[this.siblingPtr*2], 0, this.siblingPtr);
+ System.arraycopy(this.parentLineRange, 0, this.parentLineRange = new int[this.siblingPtr*2][], 0, this.siblingPtr);
+ }
+ if (this.topSiblingParent == null) {
+ // node is a JavaScriptUnit
+ this.parentLineRange[this.siblingPtr] = previousLineRange;
+ } else {
+ int parentStart = parent.getStartPosition();
+ int firstLine = getLineNumber(parentStart, previousLineRange);
+ int lastLine = getLineNumber(parentStart + parent.getLength() - 1, previousLineRange);
+ if (this.parentLineRange[this.siblingPtr] == null) {
+ this.parentLineRange[this.siblingPtr] = new int[] {firstLine, lastLine};
+ } else {
+ int[] lineRange = this.parentLineRange[this.siblingPtr];
+ lineRange[0] = firstLine;
+ lineRange[1] = lastLine;
+ }
+ }
+ this.topSiblingParent = parent;
+ }
+ this.siblings[this.siblingPtr] = node;
+
+ // We're always ok to visit sub-levels
+ return true;
+ }
+
+ protected void endVisitNode(ASTNode node) {
+
+ // Look if a child node is waiting for trailing comments computing
+ ASTNode sibling = this.topSiblingParent == node ? (ASTNode) this.siblings[this.siblingPtr] : null;
+ if (sibling != null) {
+ try {
+ storeTrailingComments(sibling, node.getStartPosition()+node.getLength()-1, true, this.parentLineRange[this.siblingPtr]);
+ } catch (Exception ex) {
+ // Give up extended ranges at this level if unexpected exception happens...
+ }
+ }
+ // Remove sibling if needed
+ if (this.topSiblingParent != null /*not a JavaScriptUnit*/
+ && this.topSiblingParent == node) {
+ this.siblingPtr--;
+ this.topSiblingParent = node.getParent();
+ }
+ }
+
+ public boolean visit ( JavaScriptUnit node) {
+ // do nothing special, just go down in sub-levels
+ return true;
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DoStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DoStatement.java
new file mode 100644
index 0000000..d9c3514
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DoStatement.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Do statement AST node type.
+ *
+ *
+ * DoStatement:
+ * do Statement while ( Expression ) ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class DoStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(DoStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(DoStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(DoStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new unparented do statement node owned by the given
+ * AST. By default, the expresssion is unspecified, but legal,
+ * and the body statement is an empty block.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ DoStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return DO_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ DoStatement result = new DoStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody((Statement) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getBody());
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this do statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this do statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this do statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this do statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the body of a do statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the body of a DoStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DocCommentParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DocCommentParser.java
new file mode 100644
index 0000000..ea026b7
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/DocCommentParser.java
@@ -0,0 +1,696 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Internal parser used for decoding doc comments.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class DocCommentParser extends AbstractCommentParser {
+
+ private JSdoc docComment;
+ private AST ast;
+
+ DocCommentParser(AST ast, Scanner scanner, boolean check) {
+ super(null);
+ this.ast = ast;
+ this.scanner = scanner;
+ this.sourceLevel = this.ast.apiLevel() >= AST.JLS3 ? ClassFileConstants.JDK1_5 : ClassFileConstants.JDK1_3;
+ this.checkDocComment = check;
+ this.kind = DOM_PARSER | TEXT_PARSE;
+ }
+
+ public JSdoc parse(int[] positions) {
+ return parse(positions[0], positions[1]-positions[0]);
+ }
+ public JSdoc parse(int start, int length) {
+
+ // Init
+ this.source = this.scanner.source;
+ this.lineEnds = this.scanner.lineEnds;
+ this.docComment = new JSdoc(this.ast);
+
+ // Parse
+ if (this.checkDocComment) {
+ this.javadocStart = start;
+ this.javadocEnd = start+length-1;
+ this.firstTagPosition = this.javadocStart;
+ commentParse();
+ }
+ this.docComment.setSourceRange(start, length);
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ setComment(start, length); // backward compatibility
+ }
+ return this.docComment;
+ }
+
+ /**
+ * Sets the comment starting at the given position and with the given length.
+ *
+ * Note the only purpose of this method is to hide deprecated warnings.
+ * @deprecated mark deprecated to hide deprecated usage
+ */
+ private void setComment(int start, int length) {
+ this.docComment.setComment(new String(this.source, start, length));
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("javadoc: ").append(this.docComment).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(super.toString());
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#createArgumentReference(char[], java.lang.Object, int)
+ */
+ protected Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException {
+ try {
+ FunctionRefParameter argument = this.ast.newFunctionRefParameter();
+ ASTNode node = (ASTNode) typeRef;
+ int argStart = node.getStartPosition();
+ int argEnd = node.getStartPosition()+node.getLength()-1;
+ if (dim > 0) argEnd = (int) dimPositions[dim-1];
+ if (argNamePos >= 0) argEnd = (int) argNamePos;
+ if (name.length != 0) {
+ final SimpleName argName = new SimpleName(this.ast);
+ argName.internalSetIdentifier(new String(name));
+ argument.setName(argName);
+ int argNameStart = (int) (argNamePos >>> 32);
+ argName.setSourceRange(argNameStart, argEnd-argNameStart+1);
+ }
+ Type argType = null;
+ if (node.getNodeType() == ASTNode.PRIMITIVE_TYPE) {
+ argType = (PrimitiveType) node;
+// if (dim > 0) {
+// argType = this.ast.newArrayType(argType, dim);
+// argType.setSourceRange(argStart, ((int) dimPositions[dim-1])-argStart+1);
+// }
+ } else {
+ Name argTypeName = (Name) node;
+ argType = this.ast.newSimpleType(argTypeName);
+ argType.setSourceRange(argStart, node.getLength());
+ }
+ if (dim > 0 && !isVarargs) {
+ for (int i=0; i>> 32);
+ int end = (int) this.identifierPositionStack[0];
+ fieldName.setSourceRange(start, end - start + 1);
+ if (receiver == null) {
+ start = this.memberStart;
+ fieldRef.setSourceRange(start, end - start + 1);
+ } else {
+ Name typeRef = (Name) receiver;
+ fieldRef.setQualifier(typeRef);
+ start = typeRef.getStartPosition();
+ end = fieldName.getStartPosition()+fieldName.getLength()-1;
+ fieldRef.setSourceRange(start, end-start+1);
+ }
+ return fieldRef;
+ }
+ catch (ClassCastException ex) {
+ throw new InvalidInputException();
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#createMethodReference(java.lang.Object[])
+ */
+ protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException {
+ try {
+ // Create method ref
+ FunctionRef methodRef = this.ast.newFunctionRef();
+ SimpleName methodName = new SimpleName(this.ast);
+ int length = this.identifierLengthStack[0] - 1; // may be > 0 for member class constructor reference
+ methodName.internalSetIdentifier(new String(this.identifierStack[length]));
+ methodRef.setName(methodName);
+ int start = (int) (this.identifierPositionStack[length] >>> 32);
+ int end = (int) this.identifierPositionStack[length];
+ methodName.setSourceRange(start, end - start + 1);
+ // Set qualifier
+ if (receiver == null) {
+ start = this.memberStart;
+ methodRef.setSourceRange(start, end - start + 1);
+ } else {
+ Name typeRef = (Name) receiver;
+ methodRef.setQualifier(typeRef);
+ start = typeRef.getStartPosition();
+ }
+ // Add arguments
+ if (arguments != null) {
+ Iterator parameters = arguments.listIterator();
+ while (parameters.hasNext()) {
+ FunctionRefParameter param = (FunctionRefParameter) parameters.next();
+ methodRef.parameters().add(param);
+ }
+ }
+ methodRef.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1);
+ return methodRef;
+ }
+ catch (ClassCastException ex) {
+ throw new InvalidInputException();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#createTag()
+ */
+ protected void createTag() {
+ TagElement tagElement = this.ast.newTagElement();
+ int position = this.scanner.currentPosition;
+ this.scanner.resetTo(this.tagSourceStart, this.tagSourceEnd);
+ StringBuffer tagName = new StringBuffer();
+ int start = this.tagSourceStart;
+ this.scanner.getNextChar();
+ while (this.scanner.currentPosition <= (this.tagSourceEnd+1)) {
+ tagName.append(this.scanner.currentCharacter);
+ this.scanner.getNextChar();
+ }
+ tagElement.setTagName(tagName.toString());
+ if (this.inlineTagStarted) {
+ start = this.inlineTagStart;
+ TagElement previousTag = null;
+ if (this.astPtr == -1) {
+ previousTag = this.ast.newTagElement();
+ previousTag.setSourceRange(start, this.tagSourceEnd-start+1);
+ pushOnAstStack(previousTag, true);
+ } else {
+ previousTag = (TagElement) this.astStack[this.astPtr];
+ }
+ int previousStart = previousTag.getStartPosition();
+ previousTag.fragments().add(tagElement);
+ previousTag.setSourceRange(previousStart, this.tagSourceEnd-previousStart+1);
+ } else {
+ pushOnAstStack(tagElement, true);
+ }
+ tagElement.setSourceRange(start, this.tagSourceEnd-start+1);
+ this.scanner.resetTo(position, this.javadocEnd);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#createTypeReference()
+ */
+ protected Object createTypeReference(int primitiveToken) {
+ int size = this.identifierLengthStack[this.identifierLengthPtr];
+ String[] identifiers = new String[size];
+ int pos = this.identifierPtr - size + 1;
+ for (int i = 0; i < size; i++) {
+ identifiers[i] = new String(this.identifierStack[pos+i]);
+ }
+ ASTNode typeRef = null;
+ if (primitiveToken == -1) {
+ typeRef = this.ast.internalNewName(identifiers);
+ } else {
+ switch (primitiveToken) {
+ case TerminalTokens.TokenNamevoid :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ break;
+ case TerminalTokens.TokenNameboolean :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.BOOLEAN);
+ break;
+ case TerminalTokens.TokenNamebyte :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.BYTE);
+ break;
+ case TerminalTokens.TokenNamechar :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.CHAR);
+ break;
+ case TerminalTokens.TokenNamedouble :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.DOUBLE);
+ break;
+ case TerminalTokens.TokenNamefloat :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.FLOAT);
+ break;
+ case TerminalTokens.TokenNameint :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.INT);
+ break;
+ case TerminalTokens.TokenNamelong :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.LONG);
+ break;
+ case TerminalTokens.TokenNameshort :
+ typeRef = this.ast.newPrimitiveType(PrimitiveType.SHORT);
+ break;
+ default:
+ // should not happen
+ return null;
+ }
+ }
+ // Update ref for whole name
+ int start = (int) (this.identifierPositionStack[pos] >>> 32);
+// int end = (int) this.identifierPositionStack[this.identifierPtr];
+// typeRef.setSourceRange(start, end-start+1);
+ // Update references of each simple name
+ if (size > 1) {
+ Name name = (Name)typeRef;
+ int nameIndex = size;
+ for (int i=this.identifierPtr; i>pos; i--, nameIndex--) {
+ int s = (int) (this.identifierPositionStack[i] >>> 32);
+ int e = (int) this.identifierPositionStack[i];
+ name.index = nameIndex;
+ SimpleName simpleName = ((QualifiedName)name).getName();
+ simpleName.index = nameIndex;
+ simpleName.setSourceRange(s, e-s+1);
+ name.setSourceRange(start, e-start+1);
+ name = ((QualifiedName)name).getQualifier();
+ }
+ int end = (int) this.identifierPositionStack[pos];
+ name.setSourceRange(start, end-start+1);
+ name.index = nameIndex;
+ } else {
+ int end = (int) this.identifierPositionStack[pos];
+ typeRef.setSourceRange(start, end-start+1);
+ }
+ return typeRef;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#parseIdentifierTag(boolean)
+ */
+ protected boolean parseIdentifierTag(boolean report) {
+ if (super.parseIdentifierTag(report)) {
+ createTag();
+ this.index = this.tagSourceEnd+1;
+ this.scanner.resetTo(this.index, this.javadocEnd);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Parse @return tag declaration
+ */
+ protected boolean parseReturn() {
+ createTag();
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#parseTag(int)
+ */
+ protected boolean parseTag(int previousPosition) throws InvalidInputException {
+
+ // Read tag name
+ int currentPosition = this.index;
+ int token = readTokenAndConsume();
+ char[] tagName = CharOperation.NO_CHAR;
+ if (currentPosition == this.scanner.startPosition) {
+ this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+ this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+ tagName = this.scanner.getCurrentIdentifierSource();
+ } else {
+ this.tagSourceEnd = currentPosition-1;
+ }
+
+ // Try to get tag name other than javaScript identifier
+ // (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
+ if (this.scanner.currentCharacter != ' ' && !ScannerHelper.isWhitespace(this.scanner.currentCharacter)) {
+ tagNameToken: while (token != TerminalTokens.TokenNameEOF && this.index < this.scanner.eofPosition) {
+ int length = tagName.length;
+ // !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
+ switch (this.scanner.currentCharacter) {
+ case '}':
+ case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
+ case '!':
+ case '#':
+ case '%':
+ case '&':
+ case '\'':
+ case '"':
+ case ':':
+ case '<':
+ case '>':
+ break tagNameToken;
+ case '-': // allowed in tag names as this character is often used in doclets (bug 68087)
+ System.arraycopy(tagName, 0, tagName = new char[length+1], 0, length);
+ tagName[length] = this.scanner.currentCharacter;
+ break;
+ default:
+ if (this.scanner.currentCharacter == ' ' || ScannerHelper.isWhitespace(this.scanner.currentCharacter)) {
+ break tagNameToken;
+ }
+ token = readTokenAndConsume();
+ char[] ident = this.scanner.getCurrentIdentifierSource();
+ System.arraycopy(tagName, 0, tagName = new char[length+ident.length], 0, length);
+ System.arraycopy(ident, 0, tagName, length, ident.length);
+ break;
+ }
+ this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+ this.scanner.getNextChar();
+ this.index = this.scanner.currentPosition;
+ }
+ }
+ int length = tagName.length;
+ this.index = this.tagSourceEnd+1;
+ this.scanner.currentPosition = this.tagSourceEnd+1;
+ this.tagSourceStart = previousPosition;
+
+ // tage name may be empty (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=125903)
+ if (tagName.length == 0) {
+ return false;
+ }
+
+ // Decide which parse to perform depending on tag name
+ this.tagValue = NO_TAG_VALUE;
+ boolean valid = true;
+ switch (token) {
+ case TerminalTokens.TokenNameIdentifier :
+ switch (tagName[0]) {
+ case 'd':
+ if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, tagName)) {
+ this.deprecated = true;
+ this.tagValue = TAG_DEPRECATED_VALUE;
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ }
+ createTag();
+ break;
+ case 'p':
+ if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) {
+ this.tagValue = TAG_PARAM_VALUE;
+ valid = parseParam();
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'e':
+ if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) {
+ this.tagValue = TAG_EXCEPTION_VALUE;
+ valid = parseThrows();
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 's':
+ if (length == TAG_SEE_LENGTH && CharOperation.equals(TAG_SEE, tagName)) {
+ this.tagValue = TAG_SEE_VALUE;
+ if (this.inlineTagStarted) {
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+ // Cannot have @see inside inline comment
+ valid = false;
+ } else {
+ valid = parseReference();
+ }
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'l':
+ if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, tagName)) {
+ this.tagValue = TAG_LINK_VALUE;
+ }
+ if (this.tagValue != NO_TAG_VALUE) {
+ if (this.inlineTagStarted) {
+ valid = parseReference();
+ } else {
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+ // Cannot have @link outside inline comment
+ valid = false;
+ }
+ } else {
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case 'v':
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+
+ break;
+ default:
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ }
+ break;
+ case TerminalTokens.TokenNamereturn :
+ this.tagValue = TAG_RETURN_VALUE;
+ valid = parseReturn();
+ break;
+ case TerminalTokens.TokenNamethrows :
+ this.tagValue = TAG_THROWS_VALUE;
+ valid = parseThrows();
+ break;
+ case TerminalTokens.TokenNameabstract:
+ case TerminalTokens.TokenNameboolean:
+ case TerminalTokens.TokenNamebreak:
+ case TerminalTokens.TokenNamebyte:
+ case TerminalTokens.TokenNamecase:
+ case TerminalTokens.TokenNamecatch:
+ case TerminalTokens.TokenNamechar:
+ case TerminalTokens.TokenNameclass:
+ case TerminalTokens.TokenNamecontinue:
+ case TerminalTokens.TokenNamedefault:
+ case TerminalTokens.TokenNamedo:
+ case TerminalTokens.TokenNamedouble:
+ case TerminalTokens.TokenNameelse:
+ case TerminalTokens.TokenNameextends:
+ case TerminalTokens.TokenNamefalse:
+ case TerminalTokens.TokenNamefinal:
+ case TerminalTokens.TokenNamefinally:
+ case TerminalTokens.TokenNamefloat:
+ case TerminalTokens.TokenNamefor:
+ case TerminalTokens.TokenNameif:
+ case TerminalTokens.TokenNameimplements:
+ case TerminalTokens.TokenNameimport:
+ case TerminalTokens.TokenNameinstanceof:
+ case TerminalTokens.TokenNameint:
+ case TerminalTokens.TokenNameinterface:
+ case TerminalTokens.TokenNamelong:
+ case TerminalTokens.TokenNamenative:
+ case TerminalTokens.TokenNamenew:
+ case TerminalTokens.TokenNamenull:
+ case TerminalTokens.TokenNamepackage:
+ case TerminalTokens.TokenNameprivate:
+ case TerminalTokens.TokenNameprotected:
+ case TerminalTokens.TokenNamepublic:
+ case TerminalTokens.TokenNameshort:
+ case TerminalTokens.TokenNamestatic:
+ case TerminalTokens.TokenNamesuper:
+ case TerminalTokens.TokenNameswitch:
+ case TerminalTokens.TokenNamesynchronized:
+ case TerminalTokens.TokenNamethis:
+ case TerminalTokens.TokenNamethrow:
+ case TerminalTokens.TokenNametransient:
+ case TerminalTokens.TokenNametrue:
+ case TerminalTokens.TokenNametry:
+ case TerminalTokens.TokenNamevoid:
+ case TerminalTokens.TokenNamevolatile:
+ case TerminalTokens.TokenNamewhile:
+ case TerminalTokens.TokenNameundefined:
+ this.tagValue = TAG_OTHERS_VALUE;
+ createTag();
+ break;
+ }
+ this.textStart = this.index;
+ return valid;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#pushParamName(java.lang.Object)
+ */
+ protected boolean pushParamName(boolean isTypeParam) {
+ int idIndex = isTypeParam ? 1 : 0;
+ final SimpleName name = new SimpleName(this.ast);
+ name.internalSetIdentifier(new String(this.identifierStack[idIndex]));
+ int nameStart = (int) (this.identifierPositionStack[idIndex] >>> 32);
+ int nameEnd = (int) (this.identifierPositionStack[idIndex] & 0x00000000FFFFFFFFL);
+ name.setSourceRange(nameStart, nameEnd-nameStart+1);
+ TagElement paramTag = this.ast.newTagElement();
+ paramTag.setTagName(TagElement.TAG_PARAM);
+ if (isTypeParam) { // specific storage for @param (see bug 79809)
+ // '<' was stored in identifiers stack
+ TextElement text = this.ast.newTextElement();
+ text.setText(new String(this.identifierStack[0]));
+ int txtStart = (int) (this.identifierPositionStack[0] >>> 32);
+ int txtEnd = (int) (this.identifierPositionStack[0] & 0x00000000FFFFFFFFL);
+ text.setSourceRange(txtStart, txtEnd-txtStart+1);
+ paramTag.fragments().add(text);
+ // add simple name
+ paramTag.fragments().add(name);
+ // '>' was stored in identifiers stack
+ text = this.ast.newTextElement();
+ text.setText(new String(this.identifierStack[2]));
+ txtStart = (int) (this.identifierPositionStack[2] >>> 32);
+ txtEnd = (int) (this.identifierPositionStack[2] & 0x00000000FFFFFFFFL);
+ text.setSourceRange(txtStart, txtEnd-txtStart+1);
+ paramTag.fragments().add(text);
+ // set param tag source range
+ paramTag.setSourceRange(this.tagSourceStart, txtEnd-this.tagSourceStart+1);
+ } else {
+ paramTag.setSourceRange(this.tagSourceStart, nameEnd-this.tagSourceStart+1);
+ paramTag.fragments().add(name);
+ }
+ pushOnAstStack(paramTag, true);
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#pushSeeRef(java.lang.Object)
+ */
+ protected boolean pushSeeRef(Object statement) {
+ TagElement seeTag = this.ast.newTagElement();
+ ASTNode node = (ASTNode) statement;
+ seeTag.fragments().add(node);
+ int end = node.getStartPosition()+node.getLength()-1;
+ if (this.inlineTagStarted) {
+ seeTag.setSourceRange(this.inlineTagStart, end-this.inlineTagStart+1);
+ switch (this.tagValue) {
+ case TAG_LINK_VALUE:
+ seeTag.setTagName(TagElement.TAG_LINK);
+ break;
+ }
+ TagElement previousTag = null;
+ int previousStart = this.inlineTagStart;
+ if (this.astPtr == -1) {
+ previousTag = this.ast.newTagElement();
+ pushOnAstStack(previousTag, true);
+ } else {
+ previousTag = (TagElement) this.astStack[this.astPtr];
+ previousStart = previousTag.getStartPosition();
+ }
+ previousTag.fragments().add(seeTag);
+ previousTag.setSourceRange(previousStart, end-previousStart+1);
+ } else {
+ seeTag.setTagName(TagElement.TAG_SEE);
+ seeTag.setSourceRange(this.tagSourceStart, end-this.tagSourceStart+1);
+ pushOnAstStack(seeTag, true);
+ }
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
+ */
+ protected void pushText(int start, int end) {
+ TextElement text = this.ast.newTextElement();
+ text.setText(new String( this.source, start, end-start));
+ text.setSourceRange(start, end-start);
+ TagElement previousTag = null;
+ int previousStart = start;
+ if (this.astPtr == -1) {
+ previousTag = this.ast.newTagElement();
+ previousTag.setSourceRange(start, end-start);
+ pushOnAstStack(previousTag, true);
+ } else {
+ previousTag = (TagElement) this.astStack[this.astPtr];
+ previousStart = previousTag.getStartPosition();
+ }
+ if (this.inlineTagStarted) {
+ if (previousTag.fragments().size() == 0) {
+ TagElement inlineTag = this.ast.newTagElement();
+ previousTag.fragments().add(inlineTag);
+ previousTag = inlineTag;
+ } else {
+ ASTNode inlineTag = (ASTNode) previousTag.fragments().get(previousTag.fragments().size()-1);
+ if (inlineTag.getNodeType() == ASTNode.TAG_ELEMENT) {
+ previousTag = (TagElement) inlineTag;
+ previousStart = previousTag.getStartPosition();
+ }
+ }
+ }
+ previousTag.fragments().add(text);
+ previousTag.setSourceRange(previousStart, end-previousStart);
+ this.textStart = -1;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
+ */
+ protected void refreshInlineTagPosition(int previousPosition) {
+ if (this.astPtr != -1) {
+ TagElement previousTag = (TagElement) this.astStack[this.astPtr];
+ if (this.inlineTagStarted) {
+ int previousStart = previousTag.getStartPosition();
+ previousTag.setSourceRange(previousStart, previousPosition-previousStart+1);
+ if (previousTag.fragments().size() > 0) {
+ ASTNode inlineTag = (ASTNode) previousTag.fragments().get(previousTag.fragments().size()-1);
+ if (inlineTag.getNodeType() == ASTNode.TAG_ELEMENT) {
+ int inlineStart = inlineTag.getStartPosition();
+ inlineTag.setSourceRange(inlineStart, previousPosition-inlineStart+1);
+ }
+ }
+ }
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#pushThrowName(java.lang.Object)
+ */
+ protected boolean pushThrowName(Object typeRef) {
+ TagElement throwsTag = this.ast.newTagElement();
+ switch (this.tagValue) {
+ case TAG_THROWS_VALUE:
+ throwsTag.setTagName(TagElement.TAG_THROWS);
+ break;
+ case TAG_EXCEPTION_VALUE:
+ throwsTag.setTagName(TagElement.TAG_EXCEPTION);
+ break;
+ }
+ throwsTag.setSourceRange(this.tagSourceStart, this.scanner.getCurrentTokenEndPosition()-this.tagSourceStart+1);
+ throwsTag.fragments().add(typeRef);
+ pushOnAstStack(throwsTag, true);
+ return true;
+ }
+
+ /*
+ * Add stored tag elements to associated comment.
+ */
+ protected void updateDocComment() {
+ for (int idx = 0; idx <= this.astPtr; idx++) {
+ this.docComment.tags().add(this.astStack[idx]);
+ }
+ }
+
+
+ protected void createParamType(Object[] typeReference) {
+ TagElement nameRef=(TagElement)this.astStack[this.astPtr];
+ Name [] refs=null;
+ if (typeReference!=null)
+ {
+ refs = new Name[typeReference.length];
+ System.arraycopy(typeReference, 0, refs, 0, typeReference.length);
+ nameRef.fragments().add(refs[0]);
+ }
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EmptyExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EmptyExpression.java
new file mode 100644
index 0000000..5222287
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EmptyExpression.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class EmptyExpression extends Expression {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(1);
+ createPropertyList(EmptyStatement.class, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+
+ EmptyExpression(AST ast) {
+ super(ast);
+ }
+
+ void accept0(ASTVisitor visitor) {
+
+ }
+
+ ASTNode clone0(AST target) {
+ EmptyExpression result = new EmptyExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ return result;
+ }
+
+ int getNodeType0() {
+ return EMPTY_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ return this.equals(other);
+ }
+
+ int treeSize() {
+ // TODO Auto-generated method stub
+ return memSize();
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EmptyStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EmptyStatement.java
new file mode 100644
index 0000000..5d3a750
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EmptyStatement.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null statement AST node type.
+ *
+ *
+ * EmptyStatement:
+ * ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class EmptyStatement extends Statement {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(1);
+ createPropertyList(EmptyStatement.class, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented null statement node owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ EmptyStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return EMPTY_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ EmptyStatement result = new EmptyStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EnhancedForStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EnhancedForStatement.java
new file mode 100644
index 0000000..3794447
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/EnhancedForStatement.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enhanced For statement AST node type (added in JLS3 API).
+ *
+ *
+ * EnhancedForStatement:
+ * for ( FormalParameter : Expression )
+ * Statement
+ *
+ * The FormalParameter is represented by a SingleVariableDeclaration
+ * (without an initializer).
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class EnhancedForStatement extends Statement {
+
+ /**
+ * The "parameter" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor PARAMETER_PROPERTY =
+ new ChildPropertyDescriptor(EnhancedForStatement.class, "parameter", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(EnhancedForStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(EnhancedForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(EnhancedForStatement.class, properyList);
+ addProperty(PARAMETER_PROPERTY, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The parameter; lazily initialized; defaults to a unspecified,
+ * legal node.
+ */
+ private SingleVariableDeclaration parameter = null;
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for an enchanced for statement owned by the
+ * given AST. By default, the parameter and expression are unspecified
+ * but legal subtrees, and the body is an empty block.
+ *
+ * @param ast the AST that is to own this node
+ */
+ EnhancedForStatement(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == PARAMETER_PROPERTY) {
+ if (get) {
+ return getParameter();
+ } else {
+ setParameter((SingleVariableDeclaration) child);
+ return null;
+ }
+ }
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return ENHANCED_FOR_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ EnhancedForStatement result = new EnhancedForStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setParameter((SingleVariableDeclaration) getParameter().clone(target));
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getParameter());
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the formal parameter in this enhanced for statement.
+ *
+ * @return the parameter
+ */
+ public SingleVariableDeclaration getParameter() {
+ if (this.parameter == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.parameter == null) {
+ preLazyInit();
+ this.parameter = this.ast.newSingleVariableDeclaration();
+ postLazyInit(this.parameter, PARAMETER_PROPERTY);
+ }
+ }
+ }
+ return this.parameter;
+ }
+
+ /**
+ * Sets the formal parameter in this enhanced for statement.
+ *
+ * @param parameter the new parameter
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setParameter(SingleVariableDeclaration parameter) {
+ if (parameter == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.parameter;
+ preReplaceChild(oldChild, parameter, PARAMETER_PROPERTY);
+ this.parameter = parameter;
+ postReplaceChild(oldChild, parameter, PARAMETER_PROPERTY);
+ }
+
+ /**
+ * Returns the expression of this enhanced for statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this enhanced for statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this enchanced for statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this enhanced for statement.
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.parameter == null ? 0 : getParameter().treeSize())
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Expression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Expression.java
new file mode 100644
index 0000000..dec8b37
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Expression.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Abstract base class of AST nodes that represent expressions.
+ * There are several kinds of expressions.
+ *
+ *
+ * Expression:
+ * Name
+ * IntegerLiteral (includes decimal, hex, and octal forms; and long)
+ * FloatingPointLiteral (includes both float and double)
+ * CharacterLiteral
+ * NullLiteral
+ * BooleanLiteral
+ * StringLiteral
+ * TypeLiteral
+ * ThisExpression
+ * SuperFieldAccess
+ * FieldAccess
+ * Assignment
+ * ParenthesizedExpression
+ * ClassInstanceCreation
+ * ArrayCreation
+ * ArrayInitializer
+ * FunctionInvocation
+ * SuperMethodInvocation
+ * ArrayAccess
+ * InfixExpression
+ * InstanceofExpression
+ * ConditionalExpression
+ * PostfixExpression
+ * PrefixExpression
+ * CastExpression
+ * VariableDeclarationExpression
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public abstract class Expression extends ASTNode {
+
+ /**
+ * Creates a new AST node for an expression owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Expression(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Resolves and returns the compile-time constant expression value as
+ * specified in JLS2 15.28, if this expression has one. Constant expression
+ * values are unavailable unless bindings are requested when the AST is
+ * being built. If the type of the value is a primitive type, the result
+ * is the boxed equivalent (i.e., int returned as an Integer
);
+ * if the type of the value is String
, the result is the string
+ * itself. If the expression does not have a compile-time constant expression
+ * value, the result is null
.
+ *
+ * Resolving constant expressions takes into account the value of simple
+ * and qualified names that refer to constant variables (JLS2 4.12.4).
+ *
+ *
+ * Note 1: enum constants are not considered constant expressions.
+ * The result is always null
for these.
+ *
+ *
+ * Note 2: Compile-time constant expressions cannot denote null
.
+ * So technically {@link NullLiteral} nodes are not constant expressions.
+ * The result is null
for these nonetheless.
+ *
+ *
+ * @return the constant expression value, or null
if this
+ * expression has no constant expression value or if bindings were not
+ * requested when the AST was created
+ *
+ */
+ public final Object resolveConstantExpressionValue() {
+ return this.ast.getBindingResolver().resolveConstantExpressionValue(this);
+ }
+
+ /**
+ * Resolves and returns the binding for the type of this expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding for the type of this expression, or
+ * null
if the type cannot be resolved
+ */
+ public final ITypeBinding resolveTypeBinding() {
+ return this.ast.getBindingResolver().resolveExpressionType(this);
+ }
+
+ /**
+ * Returns whether this expression node is the site of a boxing
+ * conversion (JLS3 5.1.7). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return true
if this expression is the site of a
+ * boxing conversion, or false
if either no boxing conversion
+ * is involved or if bindings were not requested when the AST was created
+ *
+ */
+ public final boolean resolveBoxing() {
+ return this.ast.getBindingResolver().resolveBoxing(this);
+ }
+
+ /**
+ * Returns whether this expression node is the site of an unboxing
+ * conversion (JLS3 5.1.8). This information is available only
+ * when bindings are requested when the AST is being built.
+ *
+ * @return true
if this expression is the site of an
+ * unboxing conversion, or false
if either no unboxing
+ * conversion is involved or if bindings were not requested when the
+ * AST was created
+ *
+ */
+ public final boolean resolveUnboxing() {
+ return this.ast.getBindingResolver().resolveUnboxing(this);
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ExpressionStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ExpressionStatement.java
new file mode 100644
index 0000000..d11e4a5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ExpressionStatement.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Expression statement AST node type.
+ *
+ * This kind of node is used to convert an expression (Expression
)
+ * into a statement (Statement
) by wrapping it.
+ *
+ *
+ * ExpressionStatement:
+ * StatementExpression ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ExpressionStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ExpressionStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ExpressionStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new unparented expression statement node owned by the given
+ * AST. By default, the expression statement is unspecified, but legal,
+ * method invocation expression.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ExpressionStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return EXPRESSION_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ExpressionStatement result = new ExpressionStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this expression statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new FunctionInvocation(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this expression statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FieldAccess.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FieldAccess.java
new file mode 100644
index 0000000..6a01a4e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FieldAccess.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Field access expression AST node type.
+ *
+ *
+ * FieldAccess:
+ * Expression . Identifier
+ *
+ *
+ *
+ * Note that there are several kinds of expressions that resemble field access
+ * expressions: qualified names, this expressions, and super field access
+ * expressions. The following guidelines help with correct usage:
+ *
+ * - An expression like "foo.this" can only be represented as a this
+ * expression (
ThisExpression
) containing a simple name.
+ * "this" is a keyword, and therefore invalid as an identifier.
+ * - An expression like "this.foo" can only be represented as a field
+ * access expression (
FieldAccess
) containing a this expression
+ * and a simple name. Again, this is because "this" is a keyword, and
+ * therefore invalid as an identifier.
+ * - An expression with "super" can only be represented as a super field
+ * access expression (
SuperFieldAccess
). "super" is a also
+ * keyword, and therefore invalid as an identifier.
+ * - An expression like "foo.bar" can be represented either as a
+ * qualified name (
QualifiedName
) or as a field access
+ * expression (FieldAccess
) containing simple names. Either
+ * is acceptable, and there is no way to choose between them without
+ * information about what the names resolve to
+ * (ASTParser
may return either).
+ * - Other expressions ending in an identifier, such as "foo().bar" can
+ * only be represented as field access expressions
+ * (
FieldAccess
).
+ *
+ *
+ *
+ * @see QualifiedName
+ * @see ThisExpression
+ * @see SuperFieldAccess
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FieldAccess extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(FieldAccess.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(FieldAccess.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(FieldAccess.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression expression = null;
+
+ /**
+ * The field; lazily initialized; defaults to an unspecified,
+ * but legal, simple field name.
+ */
+ private SimpleName fieldName = null;
+
+ /**
+ * Creates a new unparented node for a field access expression owned by the
+ * given AST. By default, the expression and field are both unspecified,
+ * but legal, names.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ FieldAccess(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FIELD_ACCESS;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FieldAccess result = new FieldAccess(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setName((SimpleName) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this field access expression.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this field access expression.
+ *
+ * @param expression the new expression
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the field accessed in this field access expression.
+ *
+ * @return the field name
+ */
+ public SimpleName getName() {
+ if (this.fieldName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.fieldName == null) {
+ preLazyInit();
+ this.fieldName = new SimpleName(this.ast);
+ postLazyInit(this.fieldName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.fieldName;
+ }
+
+ /**
+ * Sets the name of the field accessed in this field access expression.
+ *
+ * @param fieldName the field name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName fieldName) {
+ if (fieldName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.fieldName;
+ preReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ this.fieldName = fieldName;
+ postReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /**
+ * Resolves and returns the binding for the field accessed by this
+ * expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the variable binding, or null
if the binding cannot
+ * be resolved
+ *
+ */
+ public IVariableBinding resolveFieldBinding() {
+ return this.ast.getBindingResolver().resolveField(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.fieldName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FieldDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FieldDeclaration.java
new file mode 100644
index 0000000..5196b64
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FieldDeclaration.java
@@ -0,0 +1,372 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Field declaration node type.
+ *
+ * This kind of node collects several variable declaration fragments
+ * (VariableDeclarationFragment
) into a single body declaration
+ * (BodyDeclaration
), all sharing the same modifiers and base type.
+ *
+ *
+ * FieldDeclaration:
+ * [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
+ * { , VariableDeclarationFragment } ;
+ *
+ *
+ * When a jsdoc comment is present, the source range begins with the first
+ * character of the "/**" comment delimiter. When there is no jsdoc comment,
+ * the source range begins with the first character of the initial modifier or
+ * type. The source range extends through the last character of the final ";".
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FieldDeclaration extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(FieldDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(FieldDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(FieldDeclaration.class);
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(FieldDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type).
+ *
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(FieldDeclaration.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(FieldDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(FRAGMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(5);
+ createPropertyList(FieldDeclaration.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(FRAGMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The base type; lazily initialized; defaults to an unspecified,
+ * legal type.
+ */
+ private Type baseType = null;
+
+ /**
+ * The list of variable declaration fragments (element type:
+ * ). Defaults to an empty list.
+ */
+ private ASTNode.NodeList variableDeclarationFragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented field declaration statement node owned
+ * by the given AST. By default, the field declaration has: no modifiers,
+ * an unspecified (but legal) type, and an empty list of variable
+ * declaration fragments (which is syntactically illegal).
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ FieldDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((JSdoc) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FIELD_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FieldDeclaration result = new FieldDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setJavadoc(
+ (JSdoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setType((Type) getType().clone(target));
+ result.fragments().addAll(
+ ASTNode.copySubtrees(target, fragments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, this.variableDeclarationFragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the base type declared in this field declaration.
+ *
+ * N.B. The individual child variable declaration fragments may specify
+ * additional array dimensions. So the type of the variable are not
+ * necessarily exactly this type.
+ *
+ *
+ * @return the base type
+ */
+ public Type getType() {
+ if (this.baseType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.baseType == null) {
+ preLazyInit();
+ this.baseType = this.ast.newInferredType(null);
+ postLazyInit(this.baseType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.baseType;
+ }
+
+ /**
+ * Sets the base type declared in this field declaration to the given type.
+ *
+ * @param type the new base type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.baseType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.baseType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of variable declaration fragments in this field
+ * declaration. Adding and removing nodes from this list affects this node
+ * dynamically. All nodes in this list must be
+ * VariableDeclarationFragment
s; attempts to add any other
+ * type of node will trigger an exception.
+ *
+ * @return the live list of variable declaration fragments in this
+ * statement (element type: VariableDeclarationFragment
)
+ */
+ public List fragments() {
+ return this.variableDeclarationFragments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.baseType == null ? 0 : getType().treeSize())
+ + this.variableDeclarationFragments.listSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ForInStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ForInStatement.java
new file mode 100644
index 0000000..8725f0d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ForInStatement.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * For statement AST node type.
+ *
+ *
+ * ForStatement:
+ * for (
+ * [ ForInit ];
+ * [ Expression ] ;
+ * [ ForUpdate ] )
+ * Statement
+ * ForInit:
+ * Expression { , Expression }
+ * ForUpdate:
+ * Expression { , Expression }
+ *
+ *
+ * Note: When variables are declared in the initializer
+ * of a for statement such as "for (int a=1, b=2;;);
",
+ * they should be represented as a single
+ * VariableDeclarationExpression
+ * with two fragments, rather than being split up into a pair
+ * of expressions.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ForInStatement extends Statement {
+
+ /**
+ * The "initializers" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor ITERATION_VARIABLE_PROPERTY =
+ new ChildPropertyDescriptor(ForInStatement.class, "iterationVariable", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor COLLECTION_PROPERTY =
+ new ChildPropertyDescriptor(ForInStatement.class, "collection", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(ForInStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(ForInStatement.class, properyList);
+ addProperty(ITERATION_VARIABLE_PROPERTY, properyList);
+ addProperty(COLLECTION_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ private Statement iterationVariable = null;
+
+ private Expression collection = null;
+
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for a for statement owned by the given AST.
+ * By default, there are no initializers, no condition expression,
+ * no updaters, and the body is an empty block.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ForInStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == ITERATION_VARIABLE_PROPERTY) {
+ if (get) {
+ return getIterationVariable();
+ } else {
+ setIterationVariable((Statement) child);
+ return null;
+ }
+ }
+ if (property == COLLECTION_PROPERTY) {
+ if (get) {
+ return getCollection();
+ } else {
+ setCollection((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+// final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+// if (property == INITIALIZERS_PROPERTY) {
+// return initializers();
+// }
+// if (property == UPDATERS_PROPERTY) {
+// return updaters();
+// }
+// // allow default implementation to flag the error
+// return super.internalGetChildListProperty(property);
+// }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FOR_IN_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ForInStatement result = new ForInStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setIterationVariable(
+ (Statement) ASTNode.copySubtree(target, getIterationVariable()));
+ result.setCollection(
+ (Expression) ASTNode.copySubtree(target, getCollection()));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, this.iterationVariable);
+ acceptChild(visitor, getCollection());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+
+ /**
+ * Returns the condition expression of this for statement, or
+ * null
if there is none.
+ *
+ * @return the condition expression node, or null
if
+ * there is none
+ */
+ public Expression getCollection() {
+ return this.collection;
+ }
+
+ public Statement getIterationVariable() {
+ return this.iterationVariable;
+ }
+
+ /**
+ * Sets or clears the condition expression of this return statement.
+ *
+ * @param expression the condition expression node, or null
+ * if there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setCollection(Expression expression) {
+ ASTNode oldChild = this.collection;
+ preReplaceChild(oldChild, expression, COLLECTION_PROPERTY);
+ this.collection = expression;
+ postReplaceChild(oldChild, expression, COLLECTION_PROPERTY);
+ }
+
+ public void setIterationVariable(Statement statement) {
+ ASTNode oldChild = this.iterationVariable;
+ preReplaceChild(oldChild, statement, ITERATION_VARIABLE_PROPERTY);
+ this.iterationVariable = statement;
+ postReplaceChild(oldChild, statement, ITERATION_VARIABLE_PROPERTY);
+ }
+
+
+ /**
+ * Returns the body of this for statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this for statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the body of a for statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the body of a ForStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + getIterationVariable().treeSize()
+ + getCollection().treeSize()
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ForStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ForStatement.java
new file mode 100644
index 0000000..7b8c6c0
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ForStatement.java
@@ -0,0 +1,363 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * For statement AST node type.
+ *
+ *
+ * ForStatement:
+ * for (
+ * [ ForInit ];
+ * [ Expression ] ;
+ * [ ForUpdate ] )
+ * Statement
+ * ForInit:
+ * Expression { , Expression }
+ * ForUpdate:
+ * Expression { , Expression }
+ *
+ *
+ * Note: When variables are declared in the initializer
+ * of a for statement such as "for (int a=1, b=2;;);
",
+ * they should be represented as a single
+ * VariableDeclarationExpression
+ * with two fragments, rather than being split up into a pair
+ * of expressions.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ForStatement extends Statement {
+
+ /**
+ * The "initializers" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor INITIALIZERS_PROPERTY =
+ new ChildListPropertyDescriptor(ForStatement.class, "initializers", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ForStatement.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "updaters" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor UPDATERS_PROPERTY =
+ new ChildListPropertyDescriptor(ForStatement.class, "updaters", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(ForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(ForStatement.class, properyList);
+ addProperty(INITIALIZERS_PROPERTY, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(UPDATERS_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of initializer expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList initializers =
+ new ASTNode.NodeList(INITIALIZERS_PROPERTY);
+
+ /**
+ * The condition expression; null
for none; defaults to none.
+ */
+ private Expression optionalConditionExpression = null;
+
+ /**
+ * The list of update expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList updaters =
+ new ASTNode.NodeList(UPDATERS_PROPERTY);
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for a for statement owned by the given AST.
+ * By default, there are no initializers, no condition expression,
+ * no updaters, and the body is an empty block.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ForStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == INITIALIZERS_PROPERTY) {
+ return initializers();
+ }
+ if (property == UPDATERS_PROPERTY) {
+ return updaters();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FOR_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ForStatement result = new ForStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.initializers().addAll(ASTNode.copySubtrees(target, initializers()));
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ result.updaters().addAll(ASTNode.copySubtrees(target, updaters()));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.initializers);
+ acceptChild(visitor, getExpression());
+ acceptChildren(visitor, this.updaters);
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of initializer expressions in this for
+ * statement.
+ *
+ * The list should consist of either a list of so called statement
+ * expressions (JLS2, 14.8), or a single VariableDeclarationExpression
.
+ * Otherwise, the for statement would have no JavaScript source equivalent.
+ *
+ *
+ * @return the live list of initializer expressions
+ * (element type: Expression
)
+ */
+ public List initializers() {
+ return this.initializers;
+ }
+
+ /**
+ * Returns the condition expression of this for statement, or
+ * null
if there is none.
+ *
+ * @return the condition expression node, or null
if
+ * there is none
+ */
+ public Expression getExpression() {
+ return this.optionalConditionExpression;
+ }
+
+ /**
+ * Sets or clears the condition expression of this return statement.
+ *
+ * @param expression the condition expression node, or null
+ * if there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalConditionExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalConditionExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of update expressions in this for
+ * statement.
+ *
+ * The list should consist of so called statement expressions. Otherwise,
+ * the for statement would have no JavaScript source equivalent.
+ *
+ *
+ * @return the live list of update expressions
+ * (element type: Expression
)
+ */
+ public List updaters() {
+ return this.updaters;
+ }
+
+ /**
+ * Returns the body of this for statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this for statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the body of a for statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the body of a ForStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + this.initializers.listSize()
+ + this.updaters.listSize()
+ + (this.optionalConditionExpression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionBinding.java
new file mode 100644
index 0000000..fe6b7f2
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionBinding.java
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.wst.jsdt.core.IFunction;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.ITypeRoot;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.Signature;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodVerifier;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.core.JavaElement;
+import org.eclipse.wst.jsdt.internal.core.Member;
+import org.eclipse.wst.jsdt.internal.core.util.Util;
+
+/**
+ * Internal implementation of method bindings.
+ */
+class FunctionBinding implements IFunctionBinding {
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
+ Modifier.STRICTFP;
+ private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+ private org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding binding;
+ private BindingResolver resolver;
+ private ITypeBinding[] parameterTypes;
+ private String name;
+ private ITypeBinding declaringClass;
+ private ITypeBinding returnType;
+ private String key;
+
+ FunctionBinding(BindingResolver resolver, org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding binding) {
+ this.resolver = resolver;
+ this.binding = binding;
+ }
+
+ /**
+ * @see IFunctionBinding#isConstructor()
+ */
+ public boolean isConstructor() {
+ return this.binding.isConstructor();
+ }
+
+ /**
+ * @see IFunctionBinding#isDefaultConstructor()
+ *
+ */
+ public boolean isDefaultConstructor() {
+ final ReferenceBinding declaringClassBinding = this.binding.declaringClass;
+ if (declaringClassBinding.isBinaryBinding()) {
+ return false;
+ }
+ return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
+ }
+
+ /**
+ * @see IBinding#getName()
+ */
+ public String getName() {
+ if (name == null) {
+ if (this.binding.isConstructor()) {
+ name = this.getDeclaringClass().getName();
+ } else {
+ name = (this.binding.selector!=null) ? new String(this.binding.selector) : "";
+ }
+ }
+ return name;
+ }
+
+ /**
+ * @see IFunctionBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+ if (this.declaringClass == null) {
+ this.declaringClass = this.resolver.getTypeBinding(this.binding.declaringClass);
+ }
+ return declaringClass;
+ }
+
+ /**
+ * @see IFunctionBinding#getParameterTypes()
+ */
+ public ITypeBinding[] getParameterTypes() {
+ if (this.parameterTypes != null) {
+ return parameterTypes;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
+ int length = parameters == null ? 0 : parameters.length;
+ if (length == 0) {
+ return this.parameterTypes = NO_TYPE_BINDINGS;
+ } else {
+ ITypeBinding[] paramTypes = new ITypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ final TypeBinding parameterBinding = parameters[i];
+ if (parameterBinding != null) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(parameterBinding);
+ if (typeBinding == null) {
+ return this.parameterTypes = NO_TYPE_BINDINGS;
+ }
+ paramTypes[i] = typeBinding;
+ } else {
+ // log error
+ StringBuffer message = new StringBuffer("Report method binding where a parameter is null:\n"); //$NON-NLS-1$
+ message.append(this.toString());
+ Util.log(new IllegalArgumentException(), message.toString());
+ // report no binding since one or more parameter has no binding
+ return this.parameterTypes = NO_TYPE_BINDINGS;
+ }
+ }
+ return this.parameterTypes = paramTypes;
+ }
+ }
+
+ /**
+ * @see IFunctionBinding#getReturnType()
+ */
+ public ITypeBinding getReturnType() {
+ if (this.returnType == null) {
+ this.returnType = this.resolver.getTypeBinding(this.binding.returnType);
+ }
+ return this.returnType;
+ }
+
+ public Object getDefaultValue() {
+ return null;
+ }
+
+ public IJavaScriptElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element == null)
+ return null;
+ return element.resolved(this.binding);
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ IJavaScriptElement declaringElement = getDeclaringClass().getJavaElement();
+ if (declaringElement == null) return null;
+ if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+ ASTNode node = (ASTNode) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
+ ITypeRoot typeRoot=null;
+ IType declaringType=null;
+ if (declaringElement instanceof ITypeRoot)
+ {
+ typeRoot=(ITypeRoot)declaringElement;
+
+ }
+ else if (declaringElement instanceof IType )
+ declaringType=(IType)declaringElement;
+// IType declaringType=(IType)declaringElement;
+ if (node != null && declaringElement.getParent().getElementType() != IJavaScriptElement.CLASS_FILE) {
+ if (node instanceof FunctionDeclaration) {
+ FunctionDeclaration methodDeclaration = (FunctionDeclaration) node;
+ ArrayList parameterSignatures = new ArrayList();
+ Iterator iterator = methodDeclaration.parameters().iterator();
+ while (iterator.hasNext()) {
+ SingleVariableDeclaration parameter = (SingleVariableDeclaration) iterator.next();
+ Type type = parameter.getType();
+ String typeSig = Util.getSignature(type);
+ int arrayDim = parameter.getExtraDimensions();
+ if (parameter.getAST().apiLevel() >= AST.JLS3 && parameter.isVarargs()) {
+ arrayDim++;
+ }
+ if (arrayDim > 0) {
+ typeSig = Signature.createArraySignature(typeSig, arrayDim);
+ }
+ parameterSignatures.add(typeSig);
+ }
+ int parameterCount = parameterSignatures.size();
+ String[] parameters = new String[parameterCount];
+ parameterSignatures.toArray(parameters);
+ if (typeRoot!=null)
+ return (JavaElement) typeRoot.getFunction(getName(), parameters);
+ else
+ return (JavaElement) declaringType.getFunction(getName(), parameters);
+ }
+ else {
+ return null;
+ }
+ } else {
+ // case of method not in the created AST, or a binary method
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding original = this.binding.original();
+ String selector = original.isConstructor() ? declaringType.getElementName() : new String(original.selector);
+ boolean isBinary = declaringType.isBinary();
+ ReferenceBinding enclosingType = original.declaringClass.enclosingType();
+ boolean isInnerBinaryTypeConstructor = isBinary && original.isConstructor() && enclosingType != null;
+ TypeBinding[] parameters = original.parameters;
+ int length = parameters == null ? 0 : parameters.length;
+ int declaringIndex = isInnerBinaryTypeConstructor ? 1 : 0;
+ String[] parameterSignatures = new String[declaringIndex + length];
+ if (isInnerBinaryTypeConstructor)
+ parameterSignatures[0] = new String(enclosingType.signature()).replace('/', '.');
+ for (int i = 0; i < length; i++) {
+ parameterSignatures[declaringIndex + i] = new String(parameters[i].signature()).replace('/', '.');
+ }
+ IFunction result = declaringType.getFunction(selector, parameterSignatures);
+ if (isBinary)
+ return (JavaElement) result;
+ IFunction[] methods = null;
+ try {
+ methods = declaringType.getFunctions();
+ } catch (JavaScriptModelException e) {
+ // declaring type doesn't exist
+ return null;
+ }
+ IFunction[] candidates = Member.findMethods(result, methods);
+ if (candidates == null || candidates.length == 0)
+ return null;
+ return (JavaElement) candidates[0];
+ }
+ }
+ /**
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.METHOD;
+ }
+
+ /**
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ return this.binding.getAccessFlags() & VALID_MODIFIERS;
+ }
+
+ /**
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ return this.binding.isDeprecated();
+ }
+
+ /**
+ * @see IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.core.dom.IFunctionBinding#isVarargs()
+ *
+ */
+ public boolean isVarargs() {
+ return this.binding.isVarargs();
+ }
+
+ /**
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /**
+ * @see IBinding#isEqualTo(IBinding)
+ *
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof FunctionBinding)) {
+ return false;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding otherBinding = ((FunctionBinding) other).binding;
+ return BindingComparator.isEqual(this.binding, otherBinding);
+ }
+
+ public boolean isSubsignature(IFunctionBinding otherMethod) {
+ try {
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding other = ((FunctionBinding) otherMethod).binding;
+ if (!CharOperation.equals(this.binding.selector, other.selector))
+ return false;
+ return this.binding.areParametersEqual(other);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.core.dom.IFunctionBinding#getMethodDeclaration()
+ */
+ public IFunctionBinding getMethodDeclaration() {
+ return this.resolver.getMethodBinding(this.binding.original());
+ }
+
+ /**
+ * @see IFunctionBinding#overrides(IFunctionBinding)
+ */
+ public boolean overrides(IFunctionBinding overridenMethod) {
+ try {
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding overridenCompilerBinding = ((FunctionBinding) overridenMethod).binding;
+ if (this.binding == overridenCompilerBinding)
+ return false;
+ char[] selector = this.binding.selector;
+ if (!CharOperation.equals(selector, overridenCompilerBinding.selector))
+ return false;
+ TypeBinding match = this.binding.declaringClass.findSuperTypeWithSameErasure(overridenCompilerBinding.declaringClass);
+ if (!(match instanceof ReferenceBinding)) return false;
+
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding[] superMethods = ((ReferenceBinding)match).getMethods(selector);
+ for (int i = 0, length = superMethods.length; i < length; i++) {
+ if (superMethods[i].original() == overridenCompilerBinding) {
+ LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
+ if (lookupEnvironment == null) return false;
+ MethodVerifier methodVerifier = lookupEnvironment.methodVerifier();
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding superMethod = superMethods[i];
+ return !superMethod.isPrivate()
+ && !(superMethod.isDefault() && (superMethod.declaringClass.getPackage()) != this.binding.declaringClass.getPackage())
+ && methodVerifier.doesMethodOverride(this.binding, superMethod);
+ }
+ }
+ return false;
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /**
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionDeclaration.java
new file mode 100644
index 0000000..c056de9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionDeclaration.java
@@ -0,0 +1,871 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Etienne Pfister - bug 231122
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Method declaration AST node type. A method declaration
+ * is the union of a method declaration and a constructor declaration.
+ * For JLS2:
+ *
+ * FunctionDeclaration:
+ * [ jsdoc ] { Modifier } ( Type | void ) Identifier (
+ * [ FormalParameter
+ * { , FormalParameter } ] ) {[ ] }
+ * [ throws TypeName { , TypeName } ] ( Block | ; )
+ * ConstructorDeclaration:
+ * [ jsdoc ] { Modifier } Identifier (
+ * [ FormalParameter
+ * { , FormalParameter } ] )
+ * [throws TypeName { , TypeName } ] Block
+ *
+ * For JLS3, type parameters and reified modifiers
+ * were added:
+ *
+ * FunctionDeclaration:
+ * [ jsdoc ] { ExtendedModifier }
+ * [ < TypeParameter { , TypeParameter } > ]
+ * ( Type | void ) Identifier (
+ * [ FormalParameter
+ * { , FormalParameter } ] ) {[ ] }
+ * [ throws TypeName { , TypeName } ] ( Block | ; )
+ * ConstructorDeclaration:
+ * [ jsdoc ] { ExtendedModifier }
+ * [ < TypeParameter { , TypeParameter } > ]
+ * Identifier (
+ * [ FormalParameter
+ * { , FormalParameter } ] )
+ * [throws TypeName { , TypeName } ] Block
+ *
+ *
+ * When a jsdoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no jsdoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers), or the
+ * first character of the "<" token (method, no modifiers, type parameters),
+ * or the first character of the return type (method, no modifiers, no type
+ * parameters), or the first character of the identifier (constructor,
+ * no modifiers). The source range extends through the last character of the
+ * ";" token (if no body), or the last character of the block (if body).
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FunctionDeclaration extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(FunctionDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(FunctionDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(FunctionDeclaration.class);
+
+ /**
+ * The "constructor" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor CONSTRUCTOR_PROPERTY =
+ new SimplePropertyDescriptor(FunctionDeclaration.class, "constructor", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(FunctionDeclaration.class, "name", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "returnType" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final ChildPropertyDescriptor RETURN_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(FunctionDeclaration.class, "returnType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "returnType2" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildPropertyDescriptor RETURN_TYPE2_PROPERTY =
+ new ChildPropertyDescriptor(FunctionDeclaration.class, "returnType2", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "extraDimensions" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
+ new SimplePropertyDescriptor(FunctionDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "parameters" structural property of this node type).
+ *
+ */
+ public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(FunctionDeclaration.class, "parameters", SingleVariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "thrownExceptions" structural property of this node type).
+ *
+ */
+ public static final ChildListPropertyDescriptor THROWN_EXCEPTIONS_PROPERTY =
+ new ChildListPropertyDescriptor(FunctionDeclaration.class, "thrownExceptions", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(FunctionDeclaration.class, "body", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(10);
+ createPropertyList(FunctionDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+ addProperty(RETURN_TYPE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(PARAMETERS_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(11);
+ createPropertyList(FunctionDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+ addProperty(RETURN_TYPE2_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(PARAMETERS_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * true
for a constructor, false
for a method.
+ * Defaults to method.
+ */
+ private boolean isConstructor = false;
+
+ /**
+ * The method name; lazily initialized; defaults to an unspecified,
+ * legal JavaScript identifier.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The parameter declarations
+ * (element type: SingleVariableDeclaration
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList parameters =
+ new ASTNode.NodeList(PARAMETERS_PROPERTY);
+
+ /**
+ * The return type.
+ * JLS2 behevior: lazily initialized; defaults to void.
+ * JLS3 behavior; lazily initialized; defaults to void; null allowed.
+ * Note that this field is ignored for constructor declarations.
+ */
+ private Type returnType = null;
+
+ /**
+ * Indicated whether the return type has been initialized.
+ *
+ */
+ private boolean returnType2Initialized = false;
+
+ /**
+ * The number of array dimensions that appear after the parameters, rather
+ * than after the return type itself; defaults to 0.
+ *
+ *
+ */
+ private int extraArrayDimensions = 0;
+
+ /**
+ * The list of thrown exception names (element type: Name
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList thrownExceptions =
+ new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY);
+
+ /**
+ * The method body, or null
if none.
+ * Defaults to none.
+ */
+ private Block optionalBody = null;
+
+ /**
+ * Creates a new AST node for a method declaration owned
+ * by the given AST. By default, the declaration is for a method of an
+ * unspecified, but legal, name; no modifiers; no javadoc; no type
+ * parameters; void return type; no parameters; no array dimensions after
+ * the parameters; no thrown exceptions; and no body (as opposed to an
+ * empty body).
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ FunctionDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ if (property == EXTRA_DIMENSIONS_PROPERTY) {
+ if (get) {
+ return getExtraDimensions();
+ } else {
+ setExtraDimensions(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == CONSTRUCTOR_PROPERTY) {
+ if (get) {
+ return isConstructor();
+ } else {
+ setConstructor(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((JSdoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == RETURN_TYPE_PROPERTY) {
+ if (get) {
+ return getReturnType();
+ } else {
+ setReturnType((Type) child);
+ return null;
+ }
+ }
+ if (property == RETURN_TYPE2_PROPERTY) {
+ if (get) {
+ return getReturnType2();
+ } else {
+ setReturnType2((Type) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == PARAMETERS_PROPERTY) {
+ return parameters();
+ }
+ if (property == THROWN_EXCEPTIONS_PROPERTY) {
+ return thrownExceptions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FUNCTION_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FunctionDeclaration result = new FunctionDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setJavadoc(
+ (JSdoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ result.setReturnType(
+ (Type) ASTNode.copySubtree(target, getReturnType()));
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setReturnType2(
+ (Type) ASTNode.copySubtree(target, getReturnType2()));
+ }
+ result.setConstructor(isConstructor());
+ result.setExtraDimensions(getExtraDimensions());
+
+ SimpleName name = getName();
+ if(name != null){
+ result.setName((SimpleName) name.clone(target));
+ }
+
+ result.parameters().addAll(
+ ASTNode.copySubtrees(target, parameters()));
+ result.thrownExceptions().addAll(
+ ASTNode.copySubtrees(target, thrownExceptions()));
+ result.setBody(
+ (Block) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ acceptChild(visitor, getReturnType());
+ } else {
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getReturnType2());
+ }
+ // n.b. visit return type even for constructors
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.parameters);
+ acceptChildren(visitor, this.thrownExceptions);
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns whether this declaration declares a constructor or a method.
+ *
+ * @return true
if this is a constructor declaration,
+ * and false
if this is a method declaration
+ */
+ public boolean isConstructor() {
+ return this.isConstructor;
+ }
+
+ /**
+ * Sets whether this declaration declares a constructor or a method.
+ *
+ * @param isConstructor true
for a constructor declaration,
+ * and false
for a method declaration
+ */
+ public void setConstructor(boolean isConstructor) {
+ preValueChange(CONSTRUCTOR_PROPERTY);
+ this.isConstructor = isConstructor;
+ postValueChange(CONSTRUCTOR_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the method declared in this method declaration.
+ * For a constructor declaration, this should be the same as the name
+ * of the class.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName() {
+// if (this.methodName == null) {
+// // lazy init must be thread-safe for readers
+// synchronized (this) {
+// if (this.methodName == null) {
+// preLazyInit();
+// this.methodName = new SimpleName(this.ast);
+// postLazyInit(this.methodName, NAME_PROPERTY);
+// }
+// }
+// }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method declared in this method declaration to the
+ * given name. For a constructor declaration, this should be the same as
+ * the name of the class.
+ *
+ * @param methodName the new method name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName methodName) {
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, methodName, NAME_PROPERTY);
+ this.methodName = methodName;
+ postReplaceChild(oldChild, methodName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of method parameter declarations for this
+ * method declaration.
+ *
+ * @return the live list of method parameter declarations
+ * (element type: SingleVariableDeclaration
)
+ */
+ public List parameters() {
+ return this.parameters;
+ }
+
+ /**
+ * Returns whether this method declaration declares a
+ * variable arity method (added in JLS3 API). The convenience method checks
+ * whether the last parameter is so marked.
+ *
+ * @return true
if this is a variable arity method declaration,
+ * and false
otherwise
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @see SingleVariableDeclaration#isVarargs()
+ *
+ */
+ public boolean isVarargs() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ if (parameters().isEmpty()) {
+ return false;
+ } else {
+ SingleVariableDeclaration v = (SingleVariableDeclaration) parameters().get(parameters().size() - 1);
+ return v.isVarargs();
+ }
+ }
+
+ /**
+ * Returns the live ordered list of thrown exception names in this method
+ * declaration.
+ *
+ * @return the live list of exception names
+ * (element type: Name
)
+ */
+ public List thrownExceptions() {
+ return this.thrownExceptions;
+ }
+
+ /**
+ * Returns the return type of the method declared in this method
+ * declaration, exclusive of any extra array dimensions (JLS2 API only).
+ * This is one of the few places where the void type is meaningful.
+ *
+ * Note that this child is not relevant for constructor declarations
+ * (although, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available.
+ *
+ *
+ * @return the return type, possibly the void primitive type
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by {@link #getReturnType2()},
+ * which may return null
.
+ */
+ public Type getReturnType() {
+ return internalGetReturnType();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final Type internalGetReturnType() {
+ supportedOnlyIn2();
+ if (this.returnType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.returnType == null) {
+ preLazyInit();
+ this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ postLazyInit(this.returnType, RETURN_TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.returnType;
+ }
+
+ /**
+ * Sets the return type of the method declared in this method declaration
+ * to the given type, exclusive of any extra array dimensions (JLS2 API only). This is one
+ * of the few places where the void type is meaningful.
+ *
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ *
+ *
+ * @param type the new return type, possibly the void primitive type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setReturnType2(Type)}, which accepts null
.
+ */
+ public void setReturnType(Type type) {
+ internalSetReturnType(type);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ void internalSetReturnType(Type type) {
+ supportedOnlyIn2();
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.returnType;
+ preReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+ this.returnType = type;
+ postReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the return type of the method declared in this method
+ * declaration, exclusive of any extra array dimensions (added in JLS3 API).
+ * This is one of the few places where the void type is meaningful.
+ *
+ * Note that this child is not relevant for constructor declarations
+ * (although, if present, it does still figure in subtree equality comparisons
+ * and visits), and is devoid of the binding information ordinarily
+ * available. In the JLS2 API, the return type is mandatory.
+ * In the JLS3 API, the return type is optional.
+ *
+ *
+ * @return the return type, possibly the void primitive type,
+ * or null
if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public Type getReturnType2() {
+ unsupportedIn2();
+ if (this.returnType == null && !this.returnType2Initialized) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.returnType == null && !this.returnType2Initialized) {
+ preLazyInit();
+ this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+ this.returnType2Initialized = true;
+ postLazyInit(this.returnType, RETURN_TYPE2_PROPERTY);
+ }
+ }
+ }
+ return this.returnType;
+ }
+
+ /**
+ * Sets the return type of the method declared in this method declaration
+ * to the given type, exclusive of any extra array dimensions (added in JLS3 API).
+ * This is one of the few places where the void type is meaningful.
+ *
+ * Note that this child is not relevant for constructor declarations
+ * (although it does still figure in subtree equality comparisons and visits).
+ * In the JLS2 API, the return type is mandatory.
+ * In the JLS3 API, the return type is optional.
+ *
+ *
+ * @param type the new return type, possibly the void primitive type,
+ * or null
if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ *
+ */
+ public void setReturnType2(Type type) {
+ unsupportedIn2();
+ this.returnType2Initialized = true;
+ ASTNode oldChild = this.returnType;
+ preReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+ if (type instanceof InferredType && ((InferredType)type).getType()==null)
+ this.returnType=null;
+ else
+ this.returnType = type;
+ postReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+ }
+
+ /**
+ * Returns the number of extra array dimensions over and above the
+ * explicitly-specified return type.
+ *
+ * For example, int foo()[][]
has a return type of
+ * int
and two extra array dimensions;
+ * int[][] foo()
has a return type of int[][]
+ * and zero extra array dimensions. The two constructs have different
+ * ASTs, even though there are really syntactic variants of the same
+ * method declaration.
+ *
+ *
+ * @return the number of extra array dimensions
+ *
+ */
+ public int getExtraDimensions() {
+ return this.extraArrayDimensions;
+ }
+
+ /**
+ * Sets the number of extra array dimensions over and above the
+ * explicitly-specified return type.
+ *
+ * For example, int foo()[][]
is rendered as a return
+ * type of int
with two extra array dimensions;
+ * int[][] foo()
is rendered as a return type of
+ * int[][]
with zero extra array dimensions. The two
+ * constructs have different ASTs, even though there are really syntactic
+ * variants of the same method declaration.
+ *
+ *
+ * @param dimensions the number of array dimensions
+ * @exception IllegalArgumentException if the number of dimensions is
+ * negative
+ *
+ */
+ public void setExtraDimensions(int dimensions) {
+ if (dimensions < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ this.extraArrayDimensions = dimensions;
+ postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this method declaration, or null
if
+ * this method has no body.
+ *
+ * Note that there is a subtle difference between having no body and having
+ * an empty body ("{}").
+ *
+ *
+ * @return the method body, or null
if this method has no
+ * body
+ */
+ public Block getBody() {
+ return this.optionalBody;
+ }
+
+ /**
+ * Sets or clears the body of this method declaration.
+ *
+ * Note that there is a subtle difference between having no body
+ * (as in "void foo();"
) and having an empty body (as in
+ * "void foo() {}"). Abstract methods, and methods declared in interfaces,
+ * have no body. Non-abstract methods, and all constructors, have a body.
+ *
+ *
+ * @param body the block node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Block body) {
+ // a FunctionDeclaration may occur in a Block - must check cycles
+ ASTNode oldChild = this.optionalBody;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.optionalBody = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the method or constructor declared
+ * in this method or constructor declaration.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public IFunctionBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 9 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + (this.returnType == null ? 0 : this.returnType.treeSize())
+ + this.parameters.listSize()
+ + this.thrownExceptions.listSize()
+ + (this.optionalBody == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionExpression.java
new file mode 100644
index 0000000..bb3728d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionExpression.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Cast expression AST node type.
+ *
+ *
+ * CastExpression:
+ * ( Type ) Expression
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FunctionExpression extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor METHOD_PROPERTY =
+ new ChildPropertyDescriptor(FunctionExpression.class, "method", FunctionDeclaration.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(FunctionExpression.class, properyList);
+ addProperty(METHOD_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private FunctionDeclaration methodDeclaration = null;
+
+
+ /**
+ * Creates a new AST node for a cast expression owned by the given
+ * AST. By default, the type and expression are unspecified (but legal).
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ FunctionExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == METHOD_PROPERTY) {
+ if (get) {
+ return getMethod();
+ } else {
+ setMethod((FunctionDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FUNCTION_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FunctionExpression result = new FunctionExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setMethod((FunctionDeclaration) getMethod().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getMethod());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the type in this cast expression.
+ *
+ * @return the type
+ */
+ public FunctionDeclaration getMethod() {
+ if (this.methodDeclaration == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodDeclaration == null) {
+ preLazyInit();
+ this.methodDeclaration = this.ast.newFunctionDeclaration();
+ postLazyInit(this.methodDeclaration, METHOD_PROPERTY);
+ }
+ }
+ }
+ return this.methodDeclaration;
+ }
+
+ /**
+ * Sets the type in this cast expression to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setMethod(FunctionDeclaration method) {
+ if (method == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodDeclaration;
+ preReplaceChild(oldChild, method, METHOD_PROPERTY);
+ this.methodDeclaration = method;
+ postReplaceChild(oldChild, method, METHOD_PROPERTY);
+ }
+
+
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.methodDeclaration == null ? 0 : getMethod().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionInvocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionInvocation.java
new file mode 100644
index 0000000..a2321ea
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionInvocation.java
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Method invocation expression AST node type.
+ * For JLS2:
+ *
+ * FunctionInvocation:
+ * [ Expression . ] Identifier
+ * ( [ Expression { , Expression } ] )
+ *
+ * For JLS3, type arguments are added:
+ *
+ * FunctionInvocation:
+ * [ Expression . ]
+ * [ < Type { , Type } > ]
+ * Identifier ( [ Expression { , Expression } ] )
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FunctionInvocation extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(FunctionInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(FunctionInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(FunctionInvocation.class, "name", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(FunctionInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(FunctionInvocation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(5);
+ createPropertyList(FunctionInvocation.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ARGUMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The expression; null
for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * The type arguments (element type: Type
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The method name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript method name.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a method invocation expression owned by the
+ * given AST. By default, no expression, no type arguments,
+ * an unspecified, but legal, method name, and an empty list of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ FunctionInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FUNCTION_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FunctionInvocation result = new FunctionInvocation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (getName()!=null)
+ result.setName((SimpleName) getName().clone(target));
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ if (getName()!=null)
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this method invocation expression, or
+ * null
if there is none.
+ *
+ * @return the expression node, or null
if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Returns true
if the resolved return type has been inferred
+ * from the assignment context (JLS3 15.12.2.8), false
otherwise.
+ *
+ * This information is available only when bindings are requested when the AST is being built
+ *
.
+ *
+ * @return true
if the resolved return type has been inferred
+ * from the assignment context (JLS3 15.12.2.8), false
otherwise
+ *
+ */
+ public boolean isResolvedTypeInferredFromExpectedType() {
+ return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
+ }
+
+ /**
+ * Sets or clears the expression of this method invocation expression.
+ *
+ * @param expression the expression node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this method
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: Type
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the name of the method invoked in this expression.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+// // lazy init must be thread-safe for readers
+// synchronized (this) {
+// if (this.methodName == null) {
+// preLazyInit();
+// this.methodName = new SimpleName(this.ast);
+// postLazyInit(this.methodName, NAME_PROPERTY);
+// }
+// }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method invoked in this expression to the
+ * given name.
+ *
+ * @param name the new method name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+// if (name == null) {
+// throw new IllegalArgumentException();
+// }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this method
+ * invocation expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: Expression
)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the method invoked by this
+ * expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the method binding, or null
if the binding cannot
+ * be resolved
+ *
+ */
+ public IFunctionBinding resolveMethodBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionRef.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionRef.java
new file mode 100644
index 0000000..07d7f6f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionRef.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a method or constructor reference within a doc comment
+ * ({@link JSdoc}). The principal uses of these are in "@see" and "@link"
+ * tag elements, for references to method and constructor members.
+ *
+ * FunctionRef:
+ * [ Name ] # Identifier
+ * ( [ FunctionRefParameter | { , FunctionRefParameter } ] )
+ *
+ *
+ * @see JSdoc
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FunctionRef extends ASTNode implements IDocElement {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(FunctionRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(FunctionRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "parameters" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY =
+ new ChildListPropertyDescriptor(FunctionRef.class, "parameters", FunctionRefParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(FunctionRef.class, properyList);
+ addProperty(QUALIFIER_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(PARAMETERS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; null
for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The method name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript method name.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The parameter declarations
+ * (element type: FunctionRefParameter
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList parameters =
+ new ASTNode.NodeList(PARAMETERS_PROPERTY);
+
+
+ /**
+ * Creates a new AST node for a method reference owned by the given
+ * AST. By default, the method reference is for a method with an
+ * unspecified, but legal, name; no qualifier; and an empty parameter
+ * list.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ FunctionRef(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == PARAMETERS_PROPERTY) {
+ return parameters();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FUNCTION_REF;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FunctionRef result = new FunctionRef(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ result.parameters().addAll(
+ ASTNode.copySubtrees(target, parameters()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.parameters);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this method reference, or
+ * null
if there is none.
+ *
+ * @return the qualifier name node, or null
if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this method reference.
+ *
+ * @param name the qualifier name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the referenced method or constructor.
+ *
+ * @return the method or constructor name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodName == null) {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the referenced method or constructor to the
+ * given name.
+ *
+ * @param name the new method or constructor name node
+ * @exception IllegalArgumentException if:
+ *
+ * - the name is
null
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of method parameter references for this
+ * method reference.
+ *
+ * @return the live list of method parameter references
+ * (element type: FunctionRefParameter
)
+ */
+ public List parameters() {
+ return this.parameters;
+ }
+
+ /**
+ * Resolves and returns the binding for the entity referred to by
+ * this method reference.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public final IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveReference(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + this.parameters.listSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionRefParameter.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionRefParameter.java
new file mode 100644
index 0000000..21e0966
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/FunctionRefParameter.java
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a parameter within a method reference ({@link FunctionRef}).
+ * These nodes only occur within doc comments ({@link JSdoc}).
+ * For JLS2:
+ *
+ * FunctionRefParameter:
+ * Type [ Identifier ]
+ *
+ * For JLS3, the variable arity indicator was added:
+ *
+ * FunctionRefParameter:
+ * Type [ ... ] [ Identifier ]
+ *
+ *
+ * Note: The 1.5 spec for the jsdoc tool does not mention the possibility
+ * of a variable arity indicator in method references. However, the 1.5
+ * jsdoc tool itself does indeed support it. Since it makes sense to have
+ * a way to explicitly refer to variable arity methods, it seems more likely
+ * that the jsdoc spec is wrong in this case.
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FunctionRefParameter extends ASTNode {
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(FunctionRefParameter.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "varargs" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final SimplePropertyDescriptor VARARGS_PROPERTY =
+ new SimplePropertyDescriptor(FunctionRefParameter.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(FunctionRefParameter.class, "name", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(FunctionRefParameter.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(3);
+ createPropertyList(FunctionRefParameter.class, properyList);
+ addProperty(TYPE_PROPERTY, properyList);
+ addProperty(VARARGS_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * Indicates the last parameter of a variable arity method;
+ * defaults to false.
+ *
+ *
+ */
+ private boolean variableArity = false;
+
+ /**
+ * The parameter name, or null
if none; none by
+ * default.
+ */
+ private SimpleName optionalParameterName = null;
+
+ /**
+ * Creates a new AST node for a method referenece parameter owned by the given
+ * AST. By default, the node has an unspecified (but legal) type,
+ * not variable arity, and no parameter name.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ FunctionRefParameter(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == VARARGS_PROPERTY) {
+ if (get) {
+ return isVarargs();
+ } else {
+ setVarargs(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return FUNCTION_REF_PARAMETER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ FunctionRefParameter result = new FunctionRefParameter(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setType((Type) ASTNode.copySubtree(target, getType()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setVarargs(isVarargs());
+ }
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the paramter type.
+ *
+ * @return the parameter type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newInferredType(null);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the paramter type to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ *
+ * - the type is
null
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns whether this method reference parameter is for
+ * the last parameter of a variable arity method (added in JLS3 API).
+ *
+ * Note that the binding for the type Foo
in the vararg method
+ * reference #fun(Foo...)
is always for the type as
+ * written; i.e., the type binding for Foo
. However, if you
+ * navigate from the FunctionRef to its method binding to the
+ * type binding for its last parameter, the type binding for the vararg
+ * parameter is always an array type (i.e., Foo[]
) reflecting
+ * the way vararg methods get compiled.
+ *
+ *
+ * @return true
if this is a variable arity parameter,
+ * and false
otherwise
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public boolean isVarargs() {
+ unsupportedIn2();
+ return this.variableArity;
+ }
+
+ /**
+ * Sets whether this method reference parameter is for the last parameter of
+ * a variable arity method (added in JLS3 API).
+ *
+ * @param variableArity true
if this is a variable arity
+ * parameter, and false
otherwise
+ *
+ */
+ public void setVarargs(boolean variableArity) {
+ unsupportedIn2();
+ preValueChange(VARARGS_PROPERTY);
+ this.variableArity = variableArity;
+ postValueChange(VARARGS_PROPERTY);
+ }
+
+ /**
+ * Returns the parameter name, or null
if there is none.
+ *
+ * @return the parameter name node, or null
if there is none
+ */
+ public SimpleName getName() {
+ return this.optionalParameterName;
+ }
+
+ /**
+ * Sets or clears the parameter name.
+ *
+ * @param name the parameter name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+ ASTNode oldChild = this.optionalParameterName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.optionalParameterName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 5;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.type == null ? 0 : getType().treeSize())
+ + (this.optionalParameterName == null ? 0 : getName().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IBinding.java
new file mode 100644
index 0000000..dfe1271
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IBinding.java
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A binding represents a named entity in the JavaScript language. The world of
+ * bindings provides an integrated picture of the structure of the program as
+ * seen from the compiler's point of view. This interface declare protocol
+ * common to the various different kinds of named entities in the JavaScript language:
+ * packages, types, fields, methods, constructors, and local variables.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see IPackageBinding
+ * @see ITypeBinding
+ * @see IVariableBinding
+ * @see IFunctionBinding
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public interface IBinding {
+
+ /**
+ * Kind constant (value 1) indicating a package binding.
+ * Bindings of this kind can be safely cast to IPackageBinding
.
+ *
+ * @see #getKind()
+ * @see IPackageBinding
+ */
+ public static final int PACKAGE = 1;
+
+ /**
+ * Kind constant (value 2) indicating a type binding.
+ * Bindings of this kind can be safely cast to ITypeBinding
.
+ *
+ * @see #getKind()
+ * @see ITypeBinding
+ */
+ public static final int TYPE = 2;
+
+ /**
+ * Kind constant (value 3) indicating a field or local variable binding.
+ * Bindings of this kind can be safely cast to IVariableBinding
.
+ *
+ * @see #getKind()
+ * @see IVariableBinding
+ */
+ public static final int VARIABLE = 3;
+
+ /**
+ * Kind constant (value 4) indicating a method or constructor binding.
+ * Bindings of this kind can be safely cast to IFunctionBinding
.
+ *
+ * @see #getKind()
+ * @see IFunctionBinding
+ */
+ public static final int METHOD = 4;
+
+
+
+ /**
+ * Returns the kind of bindings this is. That is one of the kind constants:
+ * PACKAGE
,
+ * TYPE
,
+ * VARIABLE
,
+ * METHOD
,
+ * or MEMBER_VALUE_PAIR
.
+ *
+ * Note that additional kinds might be added in the
+ * future, so clients should not assume this list is exhaustive and
+ * should program defensively, e.g. by having a reasonable default
+ * in a switch statement.
+ *
+ * @return one of the kind constants
+ */
+ public int getKind();
+
+ /**
+ * Returns the name of this binding.
+ * Details of the name are specified with each specific kind of binding.
+ *
+ * @return the name of this binding
+ */
+ public String getName();
+
+ /**
+ * Returns the modifiers for this binding.
+ *
+ * Note that deprecated is not included among the modifiers.
+ * Use isDeprecated
to find out whether a binding is deprecated.
+ *
+ *
+ * @return the bit-wise or of Modifier
constants
+ * @see Modifier
+ */
+ public int getModifiers();
+
+ /**
+ * Return whether this binding is for something that is deprecated.
+ * A deprecated class, interface, field, method, or constructor is one that
+ * is marked with the 'deprecated' tag in its jsdoc comment.
+ *
+ * @return true
if this binding is deprecated, and
+ * false
otherwise
+ */
+ public boolean isDeprecated();
+
+ /**
+ * Return whether this binding is created because the bindings recovery is enabled. This binding is considered
+ * to be incomplete. Its internal state might be incomplete.
+ *
+ * @return true
if this binding is a recovered binding, and
+ * false
otherwise
+ *
+ */
+ public boolean isRecovered();
+
+ /**
+ * Returns the JavaScript element that corresponds to this binding.
+ * Returns null
if this binding has no corresponding
+ * JavaScript element.
+ *
+ * For array types, this method returns the JavaScript element that corresponds
+ * to the array's element type. For raw and parameterized types, this method
+ * returns the JavaScript element of the erasure. For annotations, this methods
+ * returns the JavaScript element of the annotation type.
+ *
+ *
+ * Here are the cases where a null
should be expected:
+ *
+ * - primitive types, including void
+ * - null type
+ * - capture types
+ * - array types of any of the above
+ * - the "length" field of an array type
+ * - the default constructor of a source class
+ * - the constructor of an anonymous class
+ * - member value pairs
+ *
+ * For all other kind of type, method, variable, annotation and package bindings,
+ * this method returns non-null
.
+ *
+ *
+ * @return the JavaScript element that corresponds to this binding,
+ * or null
if none
+ *
+ */
+ public IJavaScriptElement getJavaElement();
+
+ /**
+ * Returns the key for this binding.
+ *
+ * Within a connected cluster of bindings (for example, all bindings
+ * reachable from a given AST), each binding will have a distinct keys.
+ * The keys are generated in a manner that is predictable and as
+ * stable as possible. This last property makes these keys useful for
+ * comparing bindings between disconnected clusters of bindings (for example,
+ * the bindings between the "before" and "after" ASTs of the same
+ * javaScript unit).
+ *
+ *
+ * The exact details of how the keys are generated is unspecified.
+ * However, it is a function of the following information:
+ *
+ * - packages - the name of the package (for an unnamed package,
+ * some internal id)
+ * - classes or interfaces - the VM name of the type and the key
+ * of its package
+ * - array types - the key of the component type and number of
+ * dimensions
+ * - primitive types - the name of the primitive type
+ * - fields - the name of the field and the key of its declaring
+ * type
+ * - methods - the name of the method, the key of its declaring
+ * type, and the keys of the parameter types
+ * - constructors - the key of its declaring class, and the
+ * keys of the parameter types
+ * - local variables - the name of the local variable, the index of the
+ * declaring block relative to its parent, the key of its method
+ * - local types - the name of the type, the index of the declaring
+ * block relative to its parent, the key of its method
+ * - anonymous types - the occurence count of the anonymous
+ * type relative to its declaring type, the key of its declaring type
+ * - enum types - treated like classes
+ * - annotation types - treated like interfaces
+ * - type variables - the name of the type variable and
+ * the key of the generic type or generic method that declares that
+ * type variable
+ * - generic type instances - the key of the generic type and the keys
+ * of the type arguments used to instantiate it, and whether the
+ * instance is explicit (a parameterized type reference) or
+ * implicit (a raw type reference)
+ * - generic method instances - the key of the generic method and the keys
+ * of the type arguments used to instantiate it, and whether the
+ * instance is explicit (a parameterized method reference) or
+ * implicit (a raw method reference)
+ * - members of generic type instances - the key of the generic type
+ * instance and the key of the corresponding member in the generic
+ * type
+ *
+ *
+ * Note that the key for annotation bindings and member value pair bindings is
+ * not yet implemented. This returns null
for these 2 kinds of bindings.
+ * Recovered bindings have a unique key.
+ *
+ *
+ * @return the key for this binding
+ */
+ public String getKey();
+
+ /**
+ * There is no special definition of equality for bindings; equality is
+ * simply object identity. Within the context of a single cluster of
+ * bindings, each binding is represented by a distinct object. However,
+ * between different clusters of bindings, the binding objects may or may
+ * not be different; in these cases, the client should compare bindings
+ * using {@link #isEqualTo(IBinding)}, which checks their keys.
+ *
+ * @param obj {@inheritDoc}
+ * @return {@inheritDoc}
+ */
+ public boolean equals(Object obj);
+
+ /**
+ * Returns whether this binding has the same key as that of the given
+ * binding. Within the context of a single cluster of bindings, each
+ * binding is represented by a distinct object. However, between
+ * different clusters of bindings, the binding objects may or may
+ * not be different objects; in these cases, the binding keys
+ * are used where available.
+ *
+ * @param binding the other binding, or null
+ * @return true
if the given binding is the identical
+ * object as this binding, or if the keys of both bindings are the
+ * same string; false
if the given binding is
+ * null
, or if the bindings do not have the same key,
+ * or if one or both of the bindings have no key
+ * @see #getKey()
+ *
+ */
+ public boolean isEqualTo(IBinding binding);
+
+ /**
+ * Returns a string representation of this binding suitable for debugging
+ * purposes only.
+ *
+ * @return a debug string
+ */
+ public String toString();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IDocElement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IDocElement.java
new file mode 100644
index 0000000..8c89def
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IDocElement.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Internal marker-type interface used to tag node types that can legitimately
+ * be included in {@link TagElement#fragments() TagElement.fragments()}.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+interface IDocElement {
+ // marker-type interfaces have no members
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IExtendedModifier.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IExtendedModifier.java
new file mode 100644
index 0000000..504c9e1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IExtendedModifier.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Common interface for AST nodes that represent modifiers or
+ * annotations.
+ *
+ * ExtendedModifier:
+ * Modifier
+ * Annotation
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IExtendedModifier {
+
+ /**
+ * Returns whether this extended modifier is a standard modifier.
+ *
+ * @return true
if this is a standard modifier
+ * (instance of {@link Modifier}), and false
otherwise
+ */
+ public boolean isModifier();
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IFunctionBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IFunctionBinding.java
new file mode 100644
index 0000000..6770fc6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IFunctionBinding.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * A method binding represents a method or constructor of a class or interface.
+ * Method bindings usually correspond directly to method or
+ * constructor declarations found in the source code.
+ * However, in certain cases of references to a generic method,
+ * the method binding may correspond to a copy of a generic method
+ * declaration with substitutions for the method's type parameters
+ * (for these, getTypeArguments
returns a non-empty
+ * list, and either isParameterizedMethod
or
+ * isRawMethod
returns true
).
+ * And in certain cases of references to a method declared in a
+ * generic type, the method binding may correspond to a copy of a
+ * method declaration with substitutions for the type's type
+ * parameters (for these, getTypeArguments
returns
+ * an empty list, and both isParameterizedMethod
and
+ * isRawMethod
return false
).
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see ITypeBinding#getDeclaredMethods()
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IFunctionBinding extends IBinding {
+
+ /**
+ * Returns whether this binding is for a constructor or a method.
+ *
+ * @return true
if this is the binding for a constructor,
+ * and false
if this is the binding for a method
+ */
+ public boolean isConstructor();
+
+ /**
+ * Returns whether this binding is known to be a compiler-generated
+ * default constructor.
+ *
+ * This method returns false
for:
+ *
+ * - methods
+ * - constructors with more than one parameter
+ * - 0-argument constructors where the binding information was obtained
+ * from a JavaScript source file containing an explicit 0-argument constructor
+ * declaration
+ * - 0-argument constructors where the binding information was obtained
+ * from a JavaScript class file (it is not possible to determine from a
+ * class file whether a 0-argument constructor was present in the source
+ * code versus generated automatically by a JavaScript compiler)
+ *
+ *
+ * @return true
if this is known to be the binding for a
+ * compiler-generated default constructor, and false
+ * otherwise
+ *
+ */
+ public boolean isDefaultConstructor();
+
+ /**
+ * Returns the name of the method declared in this binding. The method name
+ * is always a simple identifier. The name of a constructor is always the
+ * same as the declared name of its declaring class.
+ *
+ * @return the name of this method, or the declared name of this
+ * constructor's declaring class
+ */
+ public String getName();
+
+ /**
+ * Returns the type binding representing the class or interface
+ * that declares this method or constructor.
+ *
+ * @return the binding of the class or interface that declares this method
+ * or constructor
+ */
+ public ITypeBinding getDeclaringClass();
+
+ /**
+ * Returns the resolved default value of an annotation type member,
+ * or null
if the member has no default value, or if this
+ * is not the binding for an annotation type member.
+ *
+ * Resolved values are represented as follows (same as for
+ * {@link IMemberValuePairBinding#getValue()}):
+ *
+ * - Primitive type - the equivalent boxed object
+ * - java.lang.Class - the
ITypeBinding
for the class object
+ * - java.lang.String - the string value itself
+ * - enum type - the
IVariableBinding
for the enum constant
+ * - annotation type - an
IAnnotationBinding
+ * - array type - an
Object[]
whose elements are as per above
+ * (the language only allows single dimensional arrays in annotations)
+ *
+ *
+ * @return the default value of this annotation type member, or null
+ * if none or not applicable
+ *
+ */
+ public Object getDefaultValue();
+
+
+ /**
+ * Returns a list of type bindings representing the formal parameter types,
+ * in declaration order, of this method or constructor. Returns an array of
+ * length 0 if this method or constructor does not takes any parameters.
+ *
+ * Note that the binding for the last parameter type of a vararg method
+ * declaration like void fun(Foo... args)
is always for
+ * an array type (i.e., Foo[]
) reflecting the the way varargs
+ * get compiled. However, the type binding obtained directly from
+ * the SingleVariableDeclaration
for the vararg parameter
+ * is always for the type as written; i.e., the type binding for
+ * Foo
.
+ *
+ *
+ * Note: The result does not include synthetic parameters introduced by
+ * inner class emulation.
+ *
+ *
+ * @return a (possibly empty) list of type bindings for the formal
+ * parameters of this method or constructor
+ */
+ public ITypeBinding[] getParameterTypes();
+
+ /**
+ * Returns the binding for the return type of this method. Returns the
+ * special primitive void
return type for constructors.
+ *
+ * @return the binding for the return type of this method, or the
+ * void
return type for constructors
+ */
+ public ITypeBinding getReturnType();
+
+ /**
+ * Returns the binding for the method declaration corresponding to this
+ * method binding. For parameterized methods ({@link #isParameterizedMethod()})
+ * and raw methods ({@link #isRawMethod()}), this method returns the binding
+ * for the corresponding generic method. For other method bindings, this
+ * returns the same binding.
+ *
+ * Note: The one notable exception is the method Object.getClass()
,
+ * which is declared to return Class<? extends Object>
, but
+ * when invoked its return type becomes Class<? extends
+ *
R>
, where R is the compile type of
+ * the receiver of the method invocation.
+ *
+ * @return the method binding
+ *
+ */
+ public IFunctionBinding getMethodDeclaration();
+
+ /**
+ * Returns whether this method's signature is a subsignature of the given method.
+ *
+ * @return true
if this method's signature is a subsignature of the given method
+ *
+ */
+ public boolean isSubsignature(IFunctionBinding otherMethod);
+
+ /**
+ * Returns whether this is a variable arity method.
+ *
+ * Note: Variable arity ("varargs") methods were added in JLS3.
+ *
+ *
+ * @return true
if this is a variable arity method,
+ * and false
otherwise
+ *
+ */
+ public boolean isVarargs();
+
+ /**
+ * Returns whether this method overrides the given method.
+ *
+ * @param method the method that is possibly overridden
+ * @return true
if this method overrides the given method,
+ * and false
otherwise
+ *
+ */
+ public boolean overrides(IFunctionBinding method);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IPackageBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IPackageBinding.java
new file mode 100644
index 0000000..a11ed0e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IPackageBinding.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * A package binding represents a named or unnamed package.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IPackageBinding extends IBinding {
+
+ /**
+ * Returns the name of the package represented by this binding. For named
+ * packages, this is the fully qualified package name (using "." for
+ * separators). For unnamed packages, this is an empty string.
+ *
+ * @return the name of the package represented by this binding, or
+ * an empty string for an unnamed package
+ */
+ public String getName();
+
+ /**
+ * Returns whether this package is an unnamed package.
+ *
+ * @return true
if this is an unnamed package, and
+ * false
otherwise
+ */
+ public boolean isUnnamed();
+
+ /**
+ * Returns the list of name component making up the name of the package
+ * represented by this binding. For example, for the package named
+ * "com.example.tool", this method returns {"com", "example", "tool"}.
+ * Returns the empty list for unnamed packages.
+ *
+ * @return the name of the package represented by this binding, or the
+ * empty list for unnamed packages
+ */
+ public String[] getNameComponents();
+
+// /**
+// * Finds and returns the binding for the class or interface with the given
+// * name declared in this package.
+// *
+// * For top-level classes and interfaces, the name here is just the simple
+// * name of the class or interface. For nested classes and interfaces, the
+// * name is the VM class name (in other words, a name like
+// * "Outer$Inner"
as used to name the class file; see
+// * ITypeBinding.getName
).
+// *
+// *
+// * @param name the name of a class or interface
+// * @return the type binding for the class or interface with the
+// * given name declared in this package, or null
+// * if there is no such type
+// */
+// public ITypeBinding findTypeBinding(String name);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ITypeBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ITypeBinding.java
new file mode 100644
index 0000000..b4be6bd
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ITypeBinding.java
@@ -0,0 +1,612 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * A type binding represents fully-resolved type. There are a number of
+ * different kinds of type bindings:
+ *
+ * - a class - represents the class declaration;
+ * possibly with type parameters
+ * - an interface - represents the class declaration;
+ * possibly with type parameters
+ * - an enum - represents the enum declaration (enum types do not have
+ * have type parameters)
+ * - an annotation - represents the annotation type declaration
+ * (annotation types do not have have type parameters)
+ * - an array type - array types are referenced but not explicitly
+ * declared
+ * - a primitive type (including the special return type
void
)
+ * - primitive types are referenced but not explicitly declared
+ * - the null type - this is the special type of
null
+ * - a type variable - represents the declaration of a type variable;
+ * possibly with type bounds
+ * - a raw type - represents a legacy non-parameterized reference to
+ * a generic type
+ * - a parameterized type - represents an copy of a type declaration
+ * with substitutions for its type parameters
+ * - a capture - represents a capture binding
+ *
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see ITypeBinding#getDeclaredTypes()
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface ITypeBinding extends IBinding {
+
+
+ /**
+ * Answer an array type binding using the receiver and the given dimension.
+ *
+ * If the receiver is an array binding, then the resulting dimension is the given dimension
+ * plus the dimension of the receiver. Otherwise the resulting dimension is the given
+ * dimension.
+ *
+ * @param dimension the given dimension
+ * @return an array type binding
+ * @throws IllegalArgumentException:
+ * - if the receiver represents the void type
+ * - if the resulting dimensions is lower than one or greater than 255
+ *
+ *
+ */
+ public ITypeBinding createArrayType(int dimension);
+
+ /**
+ * Returns the binary name of this type binding.
+ *
+ * Note that in some cases, the binary name may be unavailable.
+ * This may happen, for example, for a local type declared in
+ * unreachable code.
+ *
+ *
+ * @return the binary name of this type, or null
+ * if the binary name is unknown
+ *
+ */
+ public String getBinaryName();
+
+ /**
+ * Returns the binding representing the component type of this array type,
+ * or null
if this is not an array type binding. The component
+ * type of an array might be an array type.
+ * This is subject to change before 3.2 release.
+ *
+ * @return the component type binding, or null
if this is
+ * not an array type
+ *
+ */
+ public ITypeBinding getComponentType();
+
+ /**
+ * Returns a list of bindings representing all the fields declared
+ * as members of this class, interface, or enum type.
+ *
+ * These include public, protected, default (package-private) access,
+ * and private fields declared by the class, but excludes inherited fields.
+ * Synthetic fields may or may not be included. Fields from binary types that
+ * reference unresolvable types may not be included.
+ *
+ * Returns an empty list if the class, interface, or enum declares no fields,
+ * and for other kinds of type bindings that do not directly have members.
+ *
+ * The resulting bindings are in no particular order.
+ *
+ * @return the list of bindings for the field members of this type,
+ * or the empty list if this type does not have field members
+ */
+ public IVariableBinding[] getDeclaredFields();
+
+ /**
+ * Returns a list of method bindings representing all the methods and
+ * constructors declared for this class, interface, enum, or annotation
+ * type.
+ * These include public, protected, default (package-private) access,
+ * and private methods Synthetic methods and constructors may or may not be
+ * included. Returns an empty list if the class, interface, or enum,
+ * type declares no methods or constructors, if the annotation type declares
+ * no members, or if this type binding represents some other kind of type
+ * binding. Methods from binary types that reference unresolvable types may
+ * not be included.
+ * The resulting bindings are in no particular order.
+ *
+ * @return the list of method bindings for the methods and constructors
+ * declared by this class, interface, enum type, or annotation type,
+ * or the empty list if this type does not declare any methods or constructors
+ */
+ public IFunctionBinding[] getDeclaredMethods();
+
+ /**
+ * Returns the declared modifiers for this class or interface binding
+ * as specified in the original source declaration of the class or
+ * interface. The result may not correspond to the modifiers in the compiled
+ * binary, since the validator may change them (in particular, for inner
+ * class emulation). The getModifiers
method should be used if
+ * the compiled modifiers are needed. Returns -1 if this type does not
+ * represent a class or interface.
+ *
+ * @return the bit-wise or of Modifier
constants
+ * @see #getModifiers()
+ * @see Modifier
+ */
+ public int getDeclaredModifiers();
+
+ /**
+ * Returns a list of type bindings representing all the types declared as
+ * members of this class, interface, or enum type.
+ * These include public, protected, default (package-private) access,
+ * and private classes, interfaces, enum types, and annotation types
+ * declared by the type, but excludes inherited types. Returns an empty
+ * list if the type declares no type members, or if this type
+ * binding represents an array type, a primitive type, a type variable,
+ * a capture, or the null type.
+ * The resulting bindings are in no particular order.
+ *
+ * @return the list of type bindings for the member types of this type,
+ * or the empty list if this type does not have member types
+ */
+ public ITypeBinding[] getDeclaredTypes();
+
+ /**
+ * Returns the type binding representing the class, interface, or enum
+ * that declares this binding.
+ *
+ * The declaring class of a member class, interface, enum, annotation
+ * type is the class, interface, or enum type of which it is a member.
+ * The declaring class of a local class or interface (including anonymous
+ * classes) is the innermost class or interface containing the expression
+ * or statement in which this type is declared.
+ *
+ * The declaring class of a type variable is the class in which the type
+ * variable is declared if it is declared on a type. It returns
+ * null
otherwise.
+ *
+ * The declaring class of a capture binding is the innermost class or
+ * interface containing the expression or statement in which this capture is
+ * declared.
+ *
+ * Array types, primitive types, the null type, top-level types,
+ * recovered binding have no declaring class.
+ *
+ *
+ * @return the binding of the type that declares this type, or
+ * null
if none
+ */
+ public ITypeBinding getDeclaringClass();
+
+ /**
+ * Returns the method binding representing the method that declares this binding
+ * of a local type or type variable.
+ *
+ * The declaring method of a local class or interface (including anonymous
+ * classes) is the innermost method containing the expression or statement in
+ * which this type is declared. Returns null
if the type
+ * is declared in an initializer.
+ *
+ *
+ * The declaring method of a type variable is the method in which the type
+ * variable is declared if it is declared on a method. It
+ * returns null
otherwise.
+ *
+ * Array types, primitive types, the null type, top-level types,
+ * capture bindings, and recovered binding have no
+ * declaring method.
+ *
+ *
+ * @return the binding of the method that declares this type, or
+ * null
if none
+ *
+ */
+ public IFunctionBinding getDeclaringMethod();
+
+ /**
+ * Returns the dimensionality of this array type, or 0
if this
+ * is not an array type binding.
+ *
+ * @return the number of dimension of this array type binding, or
+ * 0
if this is not an array type
+ */
+ public int getDimensions();
+
+ /**
+ * Returns the binding representing the element type of this array type,
+ * or null
if this is not an array type binding. The element
+ * type of an array is never itself an array type.
+ *
+ * @return the element type binding, or null
if this is
+ * not an array type
+ */
+ public ITypeBinding getElementType();
+
+ /**
+ * Returns the erasure of this type binding.
+ *
+ * - For parameterized types ({@link #isParameterizedType()})
+ * - returns the binding for the corresponding generic type.
+ * - For raw types ({@link #isRawType()})
+ * - returns the binding for the corresponding generic type.
+ * java.lang.Object in other cases.
+ * - For type variables ({@link #isTypeVariable()})
+ * - returns the binding for the erasure of the leftmost bound
+ * if it has bounds and java.lang.Object if it does not.
+ * - For captures ({@link #isCapture()})
+ * - returns the binding for the erasure of the leftmost bound
+ * if it has bounds and java.lang.Object if it does not.
+ * - For array types ({@link #isArray()}) - returns an array type of
+ * the same dimension ({@link #getDimensions()}) as this type
+ * binding for which the element type is the erasure of the element type
+ * ({@link #getElementType()}) of this type binding.
+ * - For all other type bindings - returns the identical binding.
+ *
+ *
+ * @return the erasure type binding
+ *
+ */
+ public ITypeBinding getErasure();
+
+ /**
+ * Returns the compiled modifiers for this class, interface, enum,
+ * or annotation type binding.
+ * The result may not correspond to the modifiers as declared in the
+ * original source, since the validator may change them (in particular,
+ * for inner class emulation). The getDeclaredModifiers
method
+ * should be used if the original modifiers are needed.
+ * Returns 0 if this type does not represent a class, an interface, an enum, an annotation
+ * type or a recovered type.
+ *
+ * @return the compiled modifiers for this type binding or 0
+ * if this type does not represent a class, an interface, an enum, an annotation
+ * type or a recovered type.
+ * @see #getDeclaredModifiers()
+ */
+ public int getModifiers();
+
+ /**
+ * Returns the unqualified name of the type represented by this binding
+ * if it has one.
+ *
+ * - For top-level types, member types, and local types,
+ * the name is the simple name of the type.
+ * Example:
"String"
or "Collection"
.
+ * Note that the type parameters of a generic type are not included.
+ * - For primitive types, the name is the keyword for the primitive type.
+ * Example:
"int"
.
+ * - For the null type, the name is the string "null".
+ * - For anonymous classes, which do not have a name,
+ * this method returns an empty string.
+ * - For array types, the name is the unqualified name of the component
+ * type (as computed by this method) followed by "[]".
+ * Example:
"String[]"
. Note that the component type is never an
+ * an anonymous class.
+ * - For type variables, the name is just the simple name of the
+ * type variable (type bounds are not included).
+ * Example:
"X"
.
+ * - For type bindings that correspond to particular instances of a generic
+ * type arising from a parameterized type reference,
+ * the name is the unqualified name of the erasure type (as computed by this method)
+ * followed by the names (again, as computed by this method) of the type arguments
+ * surrounded by "<>" and separated by ",".
+ * Example:
"Collection<String>"
.
+ *
+ * - For type bindings that correspond to particular instances of a generic
+ * type arising from a raw type reference, the name is the unqualified name of
+ * the erasure type (as computed by this method).
+ * Example:
"Collection"
.
+ * - Capture types do not have a name. For these types,
+ * and array types thereof, this method returns an empty string.
+ *
+ *
+ * @return the unqualified name of the type represented by this binding,
+ * or the empty string if it has none
+ * @see #getQualifiedName()
+ */
+ public String getName();
+
+ /**
+ * Returns the binding for the package in which this type is declared.
+ *
+ * The package of a recovered type reference binding is the package of the
+ * enclosing type.
+ *
+ * @return the binding for the package in which this class, interface,
+ * enum, or annotation type is declared, or null
if this type
+ * binding represents a primitive type, an array type, the null type,
+ * a type variable, a capture binding.
+ */
+ public IPackageBinding getPackage();
+
+ /**
+ * Returns the fully qualified name of the type represented by this
+ * binding if it has one.
+ *
+ * - For top-level types, the fully qualified name is the simple name of
+ * the type preceded by the package name (or unqualified if in a default package)
+ * and a ".".
+ * Example:
"java.lang.String"
or "java.util.Collection"
.
+ * Note that the type parameters of a generic type are not included.
+ * - For members of top-level types, the fully qualified name is the
+ * simple name of the type preceded by the fully qualified name of the
+ * enclosing type (as computed by this method) and a ".".
+ * Example:
"java.io.ObjectInputStream.GetField"
.
+ * If the binding is for a member type that corresponds to a particular instance
+ * of a generic type arising from a parameterized type reference, the simple
+ * name of the type is followed by the fully qualified names of the type arguments
+ * (as computed by this method) surrounded by "<>" and separated by ",".
+ * Example: "pkg.Outer.Inner<java.lang.String>"
.
+ *
+ * - For primitive types, the fully qualified name is the keyword for
+ * the primitive type.
+ * Example:
"int"
.
+ * - For the null type, the fully qualified name is the string
+ * "null".
+ * - Local types (including anonymous classes) and members of local
+ * types do not have a fully qualified name. For these types, and array
+ * types thereof, this method returns an empty string.
+ * - For array types whose component type has a fully qualified name,
+ * the fully qualified name is the fully qualified name of the component
+ * type (as computed by this method) followed by "[]".
+ * Example:
"java.lang.String[]"
.
+ * - For type variables, the fully qualified name is just the name of the
+ * type variable (type bounds are not included).
+ * Example:
"X"
.
+ * - For type bindings that correspond to particular instances of a generic
+ * type arising from a parameterized type reference,
+ * the fully qualified name is the fully qualified name of the erasure
+ * type followed by the fully qualified names of the type arguments surrounded by "<>" and separated by ",".
+ * Example:
"java.util.Collection<java.lang.String>"
.
+ *
+ * - For type bindings that correspond to particular instances of a generic
+ * type arising from a raw type reference,
+ * the fully qualified name is the fully qualified name of the erasure type.
+ * Example:
"java.util.Collection"
. Note that the
+ * the type parameters are omitted.
+ * - Capture types do not have a fully qualified name. For these types,
+ * and array types thereof, this method returns an empty string.
+ *
+ *
+ * @return the fully qualified name of the type represented by this
+ * binding, or the empty string if it has none
+ * @see #getName()
+ *
+ */
+ public String getQualifiedName();
+
+ /**
+ * Returns the type binding for the superclass of the type represented
+ * by this class binding.
+ *
+ * If this type binding represents any class other than the class
+ * java.lang.Object
, then the type binding for the direct
+ * superclass of this class is returned. If this type binding represents
+ * the class java.lang.Object
, then null
is
+ * returned.
+ *
+ * Loops that ascend the class hierarchy need a suitable termination test.
+ * Rather than test the superclass for null
, it is more
+ * transparent to check whether the class is Object
, by
+ * comparing whether the class binding is identical to
+ * ast.resolveWellKnownType("java.lang.Object")
.
+ *
+ *
+ * If this type binding represents an interface, an array type, a
+ * primitive type, the null type, a type variable, an enum type,
+ * an annotation type, or a capture binding then
+ * null
is returned.
+ *
+ *
+ * @return the superclass of the class represented by this type binding,
+ * or null
if none
+ * @see AST#resolveWellKnownType(String)
+ */
+ public ITypeBinding getSuperclass();
+
+ /**
+ * Returns the binding for the type declaration corresponding to this type
+ * binding.
+ * For parameterized types ({@link #isParameterizedType()})
+ * and most raw types ({@link #isRawType()}), this method returns the binding
+ * for the corresponding generic type.
+ * For raw member types ({@link #isRawType()}, {@link #isMember()})
+ * of a raw declaring class, the type declaration is a generic or a non-generic
+ * type.
+ * A different non-generic binding will be returned when one of the declaring
+ * types/methods was parameterized.
+ * For other type bindings, this returns the same binding.
+ *
+ * @return the type binding
+ *
+ */
+ public ITypeBinding getTypeDeclaration();
+
+ /**
+ * Returns whether this type binding represents an anonymous class.
+ *
+ * An anonymous class is a subspecies of local class, and therefore mutually
+ * exclusive with member types. Note that anonymous classes have no name
+ * (getName
returns the empty string).
+ *
+ *
+ * @return true
if this type binding is for an anonymous class,
+ * and false
otherwise
+ */
+ public boolean isAnonymous();
+
+ /**
+ * Returns whether this type binding represents an array type.
+ *
+ * @return true
if this type binding is for an array type,
+ * and false
otherwise
+ * @see #getElementType()
+ * @see #getDimensions()
+ */
+ public boolean isArray();
+
+ /**
+ * Returns whether an expression of this type can be assigned to a variable
+ * of the given type.
+ *
+ * If the receiver or the argument is a recovered type, the answer is always false,
+ * unless the two types are identical or the argument is java.lang.Object
.
+ *
+ * @param variableType the type of a variable to check compatibility against
+ * @return true
if an expression of this type can be assigned to a
+ * variable of the given type, and false
otherwise
+ *
+ */
+ public boolean isAssignmentCompatible(ITypeBinding variableType);
+
+ /**
+ * Returns whether this type is cast compatible with the given type.
+ *
+ * NOTE: The cast compatibility check performs backwards.
+ * When testing whether type B can be cast to type A, one would use:
+ * A.isCastCompatible(B)
+ *
+ *
+ * If the receiver or the argument is a recovered type, the answer is always false,
+ * unless the two types are identical or the argument is java.lang.Object
.
+ *
+ * @param type the type to check compatibility against
+ * @return true
if this type is cast compatible with the
+ * given type, and false
otherwise
+ *
+ */
+ public boolean isCastCompatible(ITypeBinding type);
+
+ /**
+ * Returns whether this type binding represents a class type or a recovered binding.
+ *
+ * @return true
if this object represents a class or a recovered binding,
+ * and false
otherwise
+ */
+ public boolean isClass();
+
+ /**
+ * Returns whether this type binding originated in source code.
+ * Returns false
for all primitive types, the null type,
+ * array types, and for all classes, interfaces, enums, annotation
+ * types, type variables, parameterized type references,
+ * raw type references, and capture bindings
+ * whose information came from a pre-compiled binary class file.
+ *
+ * @return true
if the type is in source code,
+ * and false
otherwise
+ */
+ public boolean isFromSource();
+
+ /**
+ * Returns whether this type binding represents a local class.
+ *
+ * A local class is any nested class or enum type not declared as a member
+ * of another class or interface. A local class is a subspecies of nested
+ * type, and mutually exclusive with member types. Note that anonymous
+ * classes are a subspecies of local classes.
+ *
+ *
+ * Also note that interfaces and annotation types cannot be local.
+ *
+ *
+ * @return true
if this type binding is for a local class or
+ * enum type, and false
otherwise
+ */
+ public boolean isLocal();
+
+ /**
+ * Returns whether this type binding represents a member class or
+ * interface.
+ *
+ * A member type is any type declared as a member of
+ * another type. A member type is a subspecies of nested
+ * type, and mutually exclusive with local types.
+ *
+ *
+ * @return true
if this type binding is for a member class,
+ * interface, enum, or annotation type, and false
otherwise
+ */
+ public boolean isMember();
+
+ /**
+ * Returns whether this type binding represents a nested class, interface,
+ * enum, or annotation type.
+ *
+ * A nested type is any type whose declaration occurs within
+ * the body of another. The set of nested types is disjoint from the set of
+ * top-level types. Nested types further subdivide into member types, local
+ * types, and anonymous types.
+ *
+ *
+ * @return true
if this type binding is for a nested class,
+ * interface, enum, or annotation type, and false
otherwise
+ */
+ public boolean isNested();
+
+ /**
+ * Returns whether this type binding represents the null type.
+ *
+ * The null type is the type of a NullLiteral
node.
+ *
+ *
+ * @return true
if this type binding is for the null type,
+ * and false
otherwise
+ */
+ public boolean isNullType();
+
+ /**
+ * Returns whether this type binding represents a primitive type.
+ *
+ * There are nine predefined type bindings to represent the eight primitive
+ * types and void
. These have the same names as the primitive
+ * types that they represent, namely boolean, byte, char, short, int,
+ * long, float, and double, and void.
+ *
+ *
+ * @return true
if this type binding is for a primitive type,
+ * and false
otherwise
+ */
+ public boolean isPrimitive();
+
+ /**
+ * Returns whether this type is subtype compatible with the given type.
+ *
+ * If the receiver or the argument is a recovered type, the answer is always false,
+ * unless the two types are identical or the argument is java.lang.Object
.
+ *
+ * @param type the type to check compatibility against
+ * @return true
if this type is subtype compatible with the
+ * given type, and false
otherwise
+ *
+ */
+ public boolean isSubTypeCompatible(ITypeBinding type);
+
+ /**
+ * Returns whether this type binding represents a top-level class,
+ * interface, enum, or annotation type.
+ *
+ * A top-level type is any type whose declaration does not occur within the
+ * body of another type declaration. The set of top level types is disjoint
+ * from the set of nested types.
+ *
+ *
+ * @return true
if this type binding is for a top-level class,
+ * interface, enum, or annotation type, and false
otherwise
+ */
+ public boolean isTopLevel();
+
+ public boolean isCompilationUnit();
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IVariableBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IVariableBinding.java
new file mode 100644
index 0000000..8aacfc7
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IVariableBinding.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * A variable binding represents either a field of a class or interface, or
+ * a local variable declaration (including formal parameters, local variables,
+ * and exception variables).
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see ITypeBinding#getDeclaredFields()
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public interface IVariableBinding extends IBinding {
+
+ /**
+ * Returns whether this binding is for a field.
+ * Note that this method returns true
for constants,
+ * including enum constants. This method returns false
+ * for local variables.
+ *
+ * @return true
if this is the binding for a field,
+ * and false
otherwise
+ */
+ public boolean isField();
+
+ public boolean isGlobal();
+
+ /**
+ * Returns whether this binding corresponds to a parameter.
+ *
+ * @return true
if this is the binding for a parameter,
+ * and false
otherwise
+ *
+ */
+ public boolean isParameter();
+
+ /**
+ * Returns the name of the field or local variable declared in this binding.
+ * The name is always a simple identifier.
+ *
+ * @return the name of this field or local variable
+ */
+ public String getName();
+
+ /**
+ * Returns the type binding representing the class or interface
+ * that declares this field.
+ *
+ * The declaring class of a field is the class or interface of which it is
+ * a member. Local variables have no declaring class. The field length of an
+ * array type has no declaring class.
+ *
+ *
+ * @return the binding of the class or interface that declares this field,
+ * or null
if none
+ */
+ public ITypeBinding getDeclaringClass();
+
+ /**
+ * Returns the binding for the type of this field or local variable.
+ *
+ * @return the binding for the type of this field or local variable
+ */
+ public ITypeBinding getType();
+
+ /**
+ * Returns a small integer variable id for this variable binding.
+ *
+ * Local variables inside methods: Local variables (and parameters)
+ * declared within a single method are assigned ascending ids in normal
+ * code reading order; var1.getVariableId()<var2.getVariableId() means that var1 is
+ * declared before var2.
+ *
+ *
+ * Local variables outside methods: Local variables declared in a
+ * type's static initializers (or initializer expressions of static fields)
+ * are assigned ascending ids in normal code reading order. Local variables
+ * declared in a type's instance initializers (or initializer expressions
+ * of non-static fields) are assigned ascending ids in normal code reading
+ * order. These ids are useful when checking definite assignment for
+ * static initializers (JLS 16.7) and instance initializers (JLS 16.8),
+ * respectively.
+ *
+ *
+ * Fields: Fields declared as members of a type are assigned
+ * ascending ids in normal code reading order;
+ * field1.getVariableId()<field2.getVariableId() means that field1 is declared before
+ * field2.
+ *
+ *
+ * @return a small non-negative variable id
+ */
+ public int getVariableId();
+
+ /**
+ * Returns this binding's constant value if it has one.
+ * Some variables may have a value computed at compile-time. If the type of
+ * the value is a primitive type, the result is the boxed equivalent (i.e.,
+ * int returned as an Integer
). If the type of the value is
+ * String
, the result is the string itself. If the variable has
+ * no compile-time computed value, the result is null
.
+ * (Note: compile-time constant expressions cannot denote null
;
+ * JLS2 15.28.). The result is always null
for enum constants.
+ *
+ * @return the constant value, or null
if none
+ *
+ */
+ public Object getConstantValue();
+
+ /**
+ * Returns the method binding representing the method containing the scope
+ * in which this local variable is declared.
+ *
+ * The declaring method of a method formal parameter is the method itself.
+ * For a local variable declared somewhere within the body of a method,
+ * the declaring method is the enclosing method. When local or anonymous
+ * classes are involved, the declaring method is the innermost such method.
+ * There is no declaring method for a field, or for a local variable
+ * declared in a static or instance initializer; this method returns
+ * null
in those cases.
+ *
+ *
+ * @return the binding of the method or constructor that declares this
+ * local variable, or null
if none
+ *
+ */
+ public IFunctionBinding getDeclaringMethod();
+
+ /**
+ * Returns the binding for the variable declaration corresponding to this
+ * variable binding. For a binding for a field declaration in an instance
+ * of a generic type, this method returns the binding for the corresponding
+ * field declaration in the generic type. For other variable bindings,
+ * including all ones for local variables and parameters, this method
+ * returns the same binding.
+ *
+ * @return the variable binding for the originating declaration
+ *
+ */
+ public IVariableBinding getVariableDeclaration();
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IfStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IfStatement.java
new file mode 100644
index 0000000..f5d84c9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/IfStatement.java
@@ -0,0 +1,351 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * If statement AST node type.
+ *
+ * IfStatement:
+ * if ( Expression ) Statement [ else Statement]
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class IfStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(IfStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "thenStatement" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor THEN_STATEMENT_PROPERTY =
+ new ChildPropertyDescriptor(IfStatement.class, "thenStatement", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "elseStatement" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor ELSE_STATEMENT_PROPERTY =
+ new ChildPropertyDescriptor(IfStatement.class, "elseStatement", Statement.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(IfStatement.class, properyList);
+ addProperty(EXPRESSION_PROPERTY, properyList);
+ addProperty(THEN_STATEMENT_PROPERTY, properyList);
+ addProperty(ELSE_STATEMENT_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The then statement; lazily initialized; defaults to an unspecified, but
+ * legal, statement.
+ */
+ private Statement thenStatement = null;
+
+ /**
+ * The else statement; null
for none; defaults to none.
+ */
+ private Statement optionalElseStatement = null;
+
+ /**
+ * Creates a new unparented if statement node owned by the given
+ * AST. By default, the expresssion is unspecified,
+ * but legal, the then statement is an empty block, and there is no else
+ * statement.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ IfStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == THEN_STATEMENT_PROPERTY) {
+ if (get) {
+ return getThenStatement();
+ } else {
+ setThenStatement((Statement) child);
+ return null;
+ }
+ }
+ if (property == ELSE_STATEMENT_PROPERTY) {
+ if (get) {
+ return getElseStatement();
+ } else {
+ setElseStatement((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return IF_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ IfStatement result = new IfStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setThenStatement(
+ (Statement) getThenStatement().clone(target));
+ result.setElseStatement(
+ (Statement) ASTNode.copySubtree(target, getElseStatement()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getThenStatement());
+ acceptChild(visitor, getElseStatement());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this if statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the condition of this if statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the "then" part of this if statement.
+ *
+ * @return the "then" statement node
+ */
+ public Statement getThenStatement() {
+ if (this.thenStatement == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.thenStatement == null) {
+ preLazyInit();
+ this.thenStatement = new Block(this.ast);
+ postLazyInit(this.thenStatement, THEN_STATEMENT_PROPERTY);
+ }
+ }
+ }
+ return this.thenStatement;
+ }
+
+ /**
+ * Sets the "then" part of this if statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the "then" part of an if statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the thenStatement of a IfStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the "then" statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setThenStatement(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.thenStatement;
+ preReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
+ this.thenStatement = statement;
+ postReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
+ }
+
+ /**
+ * Returns the "else" part of this if statement, or null
if
+ * this if statement has no "else" part.
+ *
+ * Note that there is a subtle difference between having no else
+ * statement and having an empty statement ("{}") or null statement (";").
+ *
+ *
+ * @return the "else" statement node, or null
if none
+ */
+ public Statement getElseStatement() {
+ return this.optionalElseStatement;
+ }
+
+ /**
+ * Sets or clears the "else" part of this if statement.
+ *
+ * Note that there is a subtle difference between having no else part
+ * (as in "if(true){}"
) and having an empty block (as in
+ * "if(true){}else{}") or null statement (as in "if(true){}else;").
+ *
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the "else" part of an if statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the elseStatement of a IfStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the "else" statement node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setElseStatement(Statement statement) {
+ ASTNode oldChild = this.optionalElseStatement;
+ preReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
+ this.optionalElseStatement = statement;
+ postReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.thenStatement == null ? 0 : getThenStatement().treeSize())
+ + (this.optionalElseStatement == null ? 0 : getElseStatement().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ImportDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ImportDeclaration.java
new file mode 100644
index 0000000..5e92bfb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ImportDeclaration.java
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Import declaration AST node type.
+ *
+ * For JLS2:
+ *
+ * ImportDeclaration:
+ * import Name [ . * ] ;
+ *
+ * For JLS3, static was added:
+ *
+ * ImportDeclaration:
+ * import [ static ] Name [ . * ] ;
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ImportDeclaration extends ASTNode {
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(ImportDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "onDemand" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor ON_DEMAND_PROPERTY =
+ new SimplePropertyDescriptor(ImportDeclaration.class, "onDemand", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "static" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final SimplePropertyDescriptor STATIC_PROPERTY =
+ new SimplePropertyDescriptor(ImportDeclaration.class, "static", boolean.class, MANDATORY); //$NON-NLS-1$
+
+
+ public static final SimplePropertyDescriptor ISFILE_PROPERTY =
+ new SimplePropertyDescriptor(ImportDeclaration.class, "isFile", boolean.class, MANDATORY); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(ImportDeclaration.class, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ON_DEMAND_PROPERTY, properyList);
+ addProperty(ISFILE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(4);
+ createPropertyList(ImportDeclaration.class, properyList);
+ addProperty(STATIC_PROPERTY, properyList);
+ addProperty(NAME_PROPERTY, properyList);
+ addProperty(ON_DEMAND_PROPERTY, properyList);
+ addProperty(ISFILE_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The import name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript identifier.
+ */
+ private Name importName = null;
+
+ /**
+ * On demand versus single type import; defaults to single type import.
+ */
+ private boolean onDemand = false;
+
+ /**
+ * Static versus regular; defaults to regular import.
+ * Added in JLS3; not used in JLS2.
+ *
+ */
+ private boolean isStatic = false;
+
+ private boolean isFile = false;
+ /**
+ * Creates a new AST node for an import declaration owned by the
+ * given AST. The import declaration initially is a regular (non-static)
+ * single type import for an unspecified, but legal, JavaScript type name.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ImportDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == ON_DEMAND_PROPERTY) {
+ if (get) {
+ return isOnDemand();
+ } else {
+ setOnDemand(value);
+ return false;
+ }
+ }
+ if (property == STATIC_PROPERTY) {
+ if (get) {
+ return isStatic();
+ } else {
+ setStatic(value);
+ return false;
+ }
+ }
+ if (property == ISFILE_PROPERTY) {
+ if (get) {
+ return isFileImport();
+ } else {
+ setIsFileImport(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return IMPORT_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ImportDeclaration result = new ImportDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setOnDemand(isOnDemand());
+ result.setIsFileImport(isFileImport());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setStatic(isStatic());
+ }
+ result.setName((Name) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name imported by this declaration.
+ *
+ * For a regular on-demand import, this is the name of a package.
+ * For a static on-demand import, this is the qualified name of
+ * a type. For a regular single-type import, this is the qualified name
+ * of a type. For a static single-type import, this is the qualified name
+ * of a static member of a type.
+ *
+ *
+ * @return the imported name node
+ */
+ public Name getName() {
+ if (this.importName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.importName == null) {
+ preLazyInit();
+ this.importName =this.ast.newQualifiedName(
+ new SimpleName(this.ast), new SimpleName(this.ast));
+ postLazyInit(this.importName, NAME_PROPERTY);
+ }
+ }
+ }
+ return importName;
+ }
+
+ /**
+ * Sets the name of this import declaration to the given name.
+ *
+ * For a regular on-demand import, this is the name of a package.
+ * For a static on-demand import, this is the qualified name of
+ * a type. For a regular single-type import, this is the qualified name
+ * of a type. For a static single-type import, this is the qualified name
+ * of a static member of a type.
+ *
+ *
+ * @param name the new import name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(Name name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.importName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.importName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns whether this import declaration is an on-demand or a
+ * single-type import.
+ *
+ * @return true
if this is an on-demand import,
+ * and false
if this is a single type import
+ */
+ public boolean isOnDemand() {
+ return onDemand;
+ }
+
+ /**
+ * Sets whether this import declaration is an on-demand or a
+ * single-type import.
+ *
+ * @param onDemand true
if this is an on-demand import,
+ * and false
if this is a single type import
+ */
+ public void setOnDemand(boolean onDemand) {
+ preValueChange(ON_DEMAND_PROPERTY);
+ this.onDemand = onDemand;
+ postValueChange(ON_DEMAND_PROPERTY);
+ }
+
+ public void setIsFileImport(boolean isFileImport) {
+ preValueChange(ISFILE_PROPERTY);
+ this.isFile = isFileImport;
+ postValueChange(ISFILE_PROPERTY);
+ }
+
+ /**
+ * Returns whether this import declaration is a static import (added in JLS3 API).
+ *
+ * @return true
if this is a static import,
+ * and false
if this is a regular import
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public boolean isStatic() {
+ unsupportedIn2();
+ return isStatic;
+ }
+
+ /**
+ * Sets whether this import declaration is a static import (added in JLS3 API).
+ *
+ * @param isStatic true
if this is a static import,
+ * and false
if this is a regular import
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public void setStatic(boolean isStatic) {
+ unsupportedIn2();
+ preValueChange(STATIC_PROPERTY);
+ this.isStatic = isStatic;
+ postValueChange(STATIC_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the package, type, field, or
+ * method named in this import declaration.
+ *
+ * The name specified in a non-static single-type import can resolve
+ * to a type (only). The name specified in a non-static on-demand
+ * import can itself resolve to either a package or a type.
+ * For static imports (introduced in JLS3), the name specified in a
+ * static on-demand import can itself resolve to a type (only).
+ * The name specified in a static single import can resolve to a
+ * type, field, or method; in cases where the name could be resolved
+ * to more than one element with that name (for example, two
+ * methods both named "max", or a method and a field), this method
+ * returns one of the plausible bindings.
+ *
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return a package, type, field, or method binding, or null
+ * if the binding cannot be resolved
+ */
+ public IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveImport(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (importName == null ? 0 : getName().treeSize());
+ }
+
+ public boolean isFileImport()
+ {
+ return isFile;
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InferredType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InferredType.java
new file mode 100644
index 0000000..d542dd8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InferredType.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferredType extends Type {
+
+ private static final List PROPERTY_DESCRIPTORS;
+
+// public static final ChildPropertyDescriptor TYPE_PROPERTY =
+// new ChildPropertyDescriptor(InferredType.class, "type", String.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ static {
+ List propertyList = new ArrayList(0);
+ createPropertyList(InferredType.class, propertyList);
+// addProperty(TYPE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ String type;
+
+
+ InferredType(AST ast) {
+ super(ast);
+ }
+
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+// acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+
+ }
+
+ ASTNode clone0(AST target) {
+ InferredType result = new InferredType(target);
+ result.setSourceRange(-1,0);
+ result.type = type;
+
+ return result;
+ }
+
+ int getNodeType0() {
+ return INFERRED_TYPE;
+ }
+
+ List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+
+ }
+
+
+ int memSize() {
+ return 0;
+ }
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ return matcher.match(this, other);
+ }
+
+ int treeSize() {
+ return 0;
+ }
+ public boolean isInferred()
+ {
+ return true;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InfixExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InfixExpression.java
new file mode 100644
index 0000000..febadf3
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InfixExpression.java
@@ -0,0 +1,546 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Infix expression AST node type.
+ *
+ * InfixExpression:
+ * Expression InfixOperator Expression { InfixOperator Expression }
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InfixExpression extends Expression {
+
+ /**
+ * Infix operators (typesafe enumeration).
+ *
+ * InfixOperator:
+ * * TIMES
+ * / DIVIDE
+ * % REMAINDER
+ * + PLUS
+ * - MINUS
+ * << LEFT_SHIFT
+ * >> RIGHT_SHIFT_SIGNED
+ * >>> RIGHT_SHIFT_UNSIGNED
+ * < LESS
+ * > GREATER
+ * <= LESS_EQUALS
+ * >= GREATER_EQUALS
+ * == EQUALS
+ * != NOT_EQUALS
+ * ^ XOR
+ * & AND
+ * | OR
+ * && CONDITIONAL_AND
+ * || CONDITIONAL_OR
+ *
+ */
+ public static class Operator {
+
+ /**
+ * The token for the operator.
+ */
+ private String token;
+
+ /**
+ * Creates a new infix operator with the given token.
+ *
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ *
+ *
+ * @param token the character sequence for the operator
+ */
+ private Operator(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return token;
+ }
+
+ /** Multiplication "*" operator. */
+ public static final Operator TIMES = new Operator("*");//$NON-NLS-1$
+ /** Division "/" operator. */
+ public static final Operator DIVIDE = new Operator("/");//$NON-NLS-1$
+ /** Remainder "%" operator. */
+ public static final Operator REMAINDER = new Operator("%");//$NON-NLS-1$
+ /** Addition (or string concatenation) "+" operator. */
+ public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
+ /** Subtraction "-" operator. */
+ public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
+ /** Left shift "<<" operator. */
+ public static final Operator LEFT_SHIFT = new Operator("<<");//$NON-NLS-1$
+ /** Signed right shift ">>" operator. */
+ public static final Operator RIGHT_SHIFT_SIGNED = new Operator(">>");//$NON-NLS-1$
+ /** Unsigned right shift ">>>" operator. */
+ public static final Operator RIGHT_SHIFT_UNSIGNED =
+ new Operator(">>>");//$NON-NLS-1$
+ /** Less than "<" operator. */
+ public static final Operator LESS = new Operator("<");//$NON-NLS-1$
+ /** Greater than ">" operator. */
+ public static final Operator GREATER = new Operator(">");//$NON-NLS-1$
+ /** Less than or equals "<=" operator. */
+ public static final Operator LESS_EQUALS = new Operator("<=");//$NON-NLS-1$
+ /** Greater than or equals ">=;" operator. */
+ public static final Operator GREATER_EQUALS = new Operator(">=");//$NON-NLS-1$
+ /** Equals "==" operator. */
+ public static final Operator EQUALS = new Operator("==");//$NON-NLS-1$
+ /** Not equals "!=" operator. */
+ public static final Operator NOT_EQUALS = new Operator("!=");//$NON-NLS-1$
+ /** Exclusive OR "^" operator. */
+ public static final Operator XOR = new Operator("^");//$NON-NLS-1$
+ /** Inclusive OR "|" operator. */
+ public static final Operator OR = new Operator("|");//$NON-NLS-1$
+ /** AND "&" operator. */
+ public static final Operator AND = new Operator("&");//$NON-NLS-1$
+ /** Conditional OR "||" operator. */
+ public static final Operator CONDITIONAL_OR = new Operator("||");//$NON-NLS-1$
+ /** Conditional AND "&&" operator. */
+ public static final Operator CONDITIONAL_AND = new Operator("&&");//$NON-NLS-1$
+
+ public static final Operator INSTANCEOF = new Operator("instanceof");//$NON-NLS-1$
+ public static final Operator IN = new Operator("in");//$NON-NLS-1$
+ public static final Operator EQUAL_EQUAL_EQUAL = new Operator("===");//$NON-NLS-1$
+ public static final Operator NOT_EQUAL_EQUAL = new Operator("!==");//$NON-NLS-1$
+
+
+ /**
+ * Map from token to operator (key type: String
;
+ * value type: Operator
).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ TIMES,
+ DIVIDE,
+ REMAINDER,
+ PLUS,
+ MINUS,
+ LEFT_SHIFT,
+ RIGHT_SHIFT_SIGNED,
+ RIGHT_SHIFT_UNSIGNED,
+ LESS,
+ GREATER,
+ LESS_EQUALS,
+ GREATER_EQUALS,
+ EQUALS,
+ NOT_EQUALS,
+ XOR,
+ OR,
+ AND,
+ CONDITIONAL_OR,
+ CONDITIONAL_AND,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the infix operator corresponding to the given string,
+ * or null
if none.
+ *
+ * toOperator
is the converse of toString
:
+ * that is, Operator.toOperator(op.toString()) == op
for
+ * all operators op
.
+ *
+ *
+ * @param token the character sequence for the operator
+ * @return the infix operator, or null
if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+
+ }
+
+ /**
+ * The "leftOperand" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InfixExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "operator" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(InfixExpression.class, "operator", InfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "rightOperand" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InfixExpression.class, "rightOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "extendedOperands" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor EXTENDED_OPERANDS_PROPERTY =
+ new ChildListPropertyDescriptor(InfixExpression.class, "extendedOperands", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(5);
+ createPropertyList(InfixExpression.class, properyList);
+ addProperty(LEFT_OPERAND_PROPERTY, properyList);
+ addProperty(OPERATOR_PROPERTY, properyList);
+ addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+ addProperty(EXTENDED_OPERANDS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The infix operator; defaults to InfixExpression.Operator.PLUS.
+ */
+ private InfixExpression.Operator operator = InfixExpression.Operator.PLUS;
+
+ /**
+ * The left operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression leftOperand = null;
+
+ /**
+ * The right operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression rightOperand = null;
+
+ /**
+ * The list of extended operand expressions (element type:
+ * Expression
). Lazily initialized; defaults to an empty list.
+ */
+ private ASTNode.NodeList extendedOperands = null;
+
+ /**
+ * Creates a new AST node for an infix expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator,
+ * left and right operands, and an empty list of additional operands.
+ *
+ * @param ast the AST that is to own this node
+ */
+ InfixExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LEFT_OPERAND_PROPERTY) {
+ if (get) {
+ return getLeftOperand();
+ } else {
+ setLeftOperand((Expression) child);
+ return null;
+ }
+ }
+ if (property == RIGHT_OPERAND_PROPERTY) {
+ if (get) {
+ return getRightOperand();
+ } else {
+ setRightOperand((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == EXTENDED_OPERANDS_PROPERTY) {
+ return extendedOperands();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return INFIX_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ InfixExpression result = new InfixExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setOperator(getOperator());
+ result.setLeftOperand((Expression) getLeftOperand().clone(target));
+ result.setRightOperand((Expression) getRightOperand().clone(target));
+ if (this.extendedOperands != null) {
+ // be careful not to trigger lazy creation of list
+ result.extendedOperands().addAll(
+ ASTNode.copySubtrees(target, this.extendedOperands()));
+ }
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLeftOperand());
+ acceptChild(visitor, getRightOperand());
+ if (this.extendedOperands != null) {
+ // be careful not to trigger lazy creation of list
+ acceptChildren(visitor, this.extendedOperands);
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this infix expression.
+ *
+ * @return the infix operator
+ */
+ public InfixExpression.Operator getOperator() {
+ return this.operator;
+ }
+
+ /**
+ * Sets the operator of this infix expression.
+ *
+ * @param operator the infix operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(InfixExpression.Operator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.operator = operator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the left operand of this infix expression.
+ *
+ * @return the left operand node
+ */
+ public Expression getLeftOperand() {
+ if (this.leftOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.leftOperand == null) {
+ preLazyInit();
+ this.leftOperand= new SimpleName(this.ast);
+ postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.leftOperand;
+ }
+
+ /**
+ * Sets the left operand of this infix expression.
+ *
+ * @param expression the left operand node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setLeftOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.leftOperand;
+ preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ this.leftOperand = expression;
+ postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ }
+
+ /**
+ * Returns the right operand of this infix expression.
+ *
+ * @return the right operand node
+ */
+ public Expression getRightOperand() {
+ if (this.rightOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.rightOperand == null) {
+ preLazyInit();
+ this.rightOperand= new SimpleName(this.ast);
+ postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.rightOperand;
+ }
+
+ /**
+ * Sets the right operand of this infix expression.
+ *
+ * @param expression the right operand node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setRightOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.rightOperand;
+ preReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
+ this.rightOperand = expression;
+ postReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
+ }
+
+ /**
+ * Returns where there are any extended operands.
+ *
+ * @return true
if there are one or more extended operands,
+ * and false
if there are no extended operands
+ */
+ public boolean hasExtendedOperands() {
+ return
+ (this.extendedOperands != null) && this.extendedOperands.size() > 0;
+ }
+
+ /**
+ * Returns the live list of extended operands.
+ *
+ * The extended operands is the preferred way of representing deeply nested
+ * expressions of the form L op R op R2 op R3...
where
+ * the same operator appears between all the operands (the most
+ * common case being lengthy string concatenation expressions). Using
+ * the extended operands keeps the trees from getting too deep; this
+ * decreases the risk is running out of thread stack space at runtime
+ * when traversing such trees.
+ * ((a + b) + c) + d would be translated to:
+ * leftOperand: a
+ * rightOperand: b
+ * extendedOperands: {c, d}
+ * operator: +
+ *
+ *
+ * @return the live list of extended operands
+ * (element type: Expression
)
+ */
+ public List extendedOperands() {
+ if (this.extendedOperands == null) {
+ // lazily initialize
+ this.extendedOperands = new ASTNode.NodeList(EXTENDED_OPERANDS_PROPERTY);
+ }
+ return this.extendedOperands;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
+ + (this.rightOperand == null ? 0 : getRightOperand().treeSize())
+ + (this.extendedOperands == null ? 0 : extendedOperands.listSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Initializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Initializer.java
new file mode 100644
index 0000000..871f7f5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Initializer.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Static or instance initializer AST node type.
+ *
+ * Initializer:
+ * [ static ] Block
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class Initializer extends BodyDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(Initializer.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(Initializer.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(Initializer.class);
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(Initializer.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(Initializer.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(4);
+ createPropertyList(Initializer.class, properyList);
+ addProperty(JAVADOC_PROPERTY, properyList);
+ addProperty(MODIFIERS2_PROPERTY, properyList);
+ addProperty(BODY_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The initializer body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * Creates a new AST node for an initializer declaration owned by the given
+ * AST. By default, the initializer has no modifiers and an empty block.
+ * The jsdoc comment is not used for initializers.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Initializer(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((JSdoc) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return INITIALIZER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ Initializer result = new Initializer(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setJavadoc(
+ (JSdoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.setBody((Block) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getJavadoc());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the body of this initializer declaration.
+ *
+ * @return the initializer body
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body= new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this initializer declaration.
+ *
+ * @param body the block node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Block body) {
+ if (body == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.body = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InstanceofExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InstanceofExpression.java
new file mode 100644
index 0000000..3f90c24
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InstanceofExpression.java
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Instanceof expression AST node type.
+ *
+ * InstanceofExpression:
+ * Expression instanceof Type
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InstanceofExpression extends Expression {
+
+ /**
+ * The "leftOperand" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InstanceofExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "rightOperand" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(InstanceofExpression.class, "rightOperand", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(InstanceofExpression.class, properyList);
+ addProperty(LEFT_OPERAND_PROPERTY, properyList);
+ addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The left operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression leftOperand = null;
+
+ /**
+ * The right operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple type.
+ */
+ private Type rightOperand = null;
+
+ /**
+ * Creates a new AST node for an instanceof expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator,
+ * left and right operands.
+ *
+ * @param ast the AST that is to own this node
+ */
+ InstanceofExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LEFT_OPERAND_PROPERTY) {
+ if (get) {
+ return getLeftOperand();
+ } else {
+ setLeftOperand((Expression) child);
+ return null;
+ }
+ }
+ if (property == RIGHT_OPERAND_PROPERTY) {
+ if (get) {
+ return getRightOperand();
+ } else {
+ setRightOperand((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return INSTANCEOF_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ InstanceofExpression result = new InstanceofExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setLeftOperand((Expression) getLeftOperand().clone(target));
+ result.setRightOperand((Type) getRightOperand().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLeftOperand());
+ acceptChild(visitor, getRightOperand());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the left operand of this instanceof expression.
+ *
+ * @return the left operand node
+ */
+ public Expression getLeftOperand() {
+ if (this.leftOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.leftOperand == null) {
+ preLazyInit();
+ this.leftOperand= new SimpleName(this.ast);
+ postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.leftOperand;
+ }
+
+ /**
+ * Sets the left operand of this instanceof expression.
+ *
+ * @param expression the left operand node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setLeftOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.leftOperand;
+ preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ this.leftOperand = expression;
+ postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+ }
+
+ /**
+ * Returns the right operand of this instanceof expression.
+ *
+ * @return the right operand node
+ */
+ public Type getRightOperand() {
+ if (this.rightOperand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.rightOperand == null) {
+ preLazyInit();
+ this.rightOperand= new SimpleType(this.ast);
+ postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.rightOperand;
+ }
+
+ /**
+ * Sets the right operand of this instanceof expression.
+ *
+ * @param referenceType the right operand node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setRightOperand(Type referenceType) {
+ if (referenceType == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.rightOperand;
+ preReplaceChild(oldChild, referenceType, RIGHT_OPERAND_PROPERTY);
+ this.rightOperand = referenceType;
+ postReplaceChild(oldChild, referenceType, RIGHT_OPERAND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
+ + (this.rightOperand == null ? 0 : getRightOperand().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InternalASTRewrite.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InternalASTRewrite.java
new file mode 100644
index 0000000..e911016
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/InternalASTRewrite.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.jsdt.core.dom.rewrite.TargetSourceRangeComputer;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.LineInformation;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.ListRewriteEvent;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.NodeInfoStore;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.NodeRewriteEvent;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore.PropertyLocation;
+
+/**
+ * Internal class: not intended to be used by client.
+ * When AST modifications recording is enabled, all changes are recorded by this class.
+ */
+class InternalASTRewrite extends NodeEventHandler {
+
+ /** root node for the rewrite: Only nodes under this root are accepted */
+ private JavaScriptUnit root;
+
+ protected final RewriteEventStore eventStore;
+ protected final NodeInfoStore nodeStore;
+ protected final Hashtable clonedNodes;
+
+ int cloneDepth = 0;
+
+ /**
+ * Constructor
+ * @param root root node of the recorded ast.
+ */
+ public InternalASTRewrite(JavaScriptUnit root) {
+ this.root = root;
+ this.eventStore = new RewriteEventStore();
+ this.nodeStore = new NodeInfoStore(root.getAST());
+ this.clonedNodes = new Hashtable();
+ }
+
+ /**
+ * Performs the rewrite: The rewrite events are translated to the corresponding in text changes.
+ * @param document Document which describes the code of the AST that is passed in in the
+ * constructor. This document is accessed read-only.
+ * @param options options
+ * @throws IllegalArgumentException if the rewrite fails
+ * @return Returns the edit describing the text changes.
+ */
+ public TextEdit rewriteAST(IDocument document, Map options) {
+ TextEdit result = new MultiTextEdit();
+
+ final JavaScriptUnit rootNode = getRootNode();
+ if (rootNode != null) {
+ TargetSourceRangeComputer xsrComputer = new TargetSourceRangeComputer() {
+ /**
+ * This implementation of
+ * {@link TargetSourceRangeComputer#computeSourceRange(ASTNode)}
+ * is specialized to work in the case of internal AST rewriting, where the
+ * original AST has been modified from its original form. This means that
+ * one cannot trust that the root of the given node is the javaScript unit.
+ */
+ public SourceRange computeSourceRange(ASTNode node) {
+ int extendedStartPosition = rootNode.getExtendedStartPosition(node);
+ int extendedLength = rootNode.getExtendedLength(node);
+ return new SourceRange(extendedStartPosition, extendedLength);
+ }
+ };
+ char[] content= document.get().toCharArray();
+ LineInformation lineInfo= LineInformation.create(document);
+ String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+ List comments= rootNode.getCommentList();
+
+ ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, comments, options, xsrComputer);
+ rootNode.accept(visitor);
+ }
+ return result;
+ }
+
+ private void markAsMoveOrCopyTarget(ASTNode node, ASTNode newChild) {
+ ASTNode source = (ASTNode)this.clonedNodes.get(newChild);
+ if(source != null) {
+ if(this.cloneDepth == 0) {
+ PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(source, RewriteEventStore.ORIGINAL);
+ CopySourceInfo sourceInfo =
+ this.eventStore.markAsCopySource(
+ propertyLocation.getParent(),
+ propertyLocation.getProperty(),
+ source,
+ false);
+ this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
+ }
+ } else if((newChild.getFlags() & ASTNode.ORIGINAL) != 0) {
+ PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(newChild, RewriteEventStore.ORIGINAL);
+ CopySourceInfo sourceInfo =
+ this.eventStore.markAsCopySource(
+ propertyLocation.getParent(),
+ propertyLocation.getProperty(),
+ newChild,
+ true);
+ this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
+ }
+ }
+
+ private JavaScriptUnit getRootNode() {
+ return this.root;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("Events:\n"); //$NON-NLS-1$
+ buf.append(this.eventStore.toString());
+ return buf.toString();
+ }
+
+ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // force event creation
+ this.getNodeEvent(node, property);
+ }
+
+ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ NodeRewriteEvent event = this.getNodeEvent(node, property);
+ event.setNewValue(node.getStructuralProperty(property));
+ }
+
+ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ if(property.isChildProperty()) {
+ NodeRewriteEvent event = this.getNodeEvent(node, property);
+ event.setNewValue(child);
+ if(child != null) {
+ this.markAsMoveOrCopyTarget(node, child);
+ }
+ } else if(property.isChildListProperty()) {
+ // force event creation
+ this.getListEvent(node, property);
+ }
+ }
+
+ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ if(property.isChildListProperty()) {
+
+ ListRewriteEvent event = this.getListEvent(node, property);
+ List list = (List)node.getStructuralProperty(property);
+ int i = list.indexOf(child);
+ int s = list.size();
+ int index;
+ if(i + 1 < s) {
+ ASTNode nextNode = (ASTNode)list.get(i + 1);
+ index = event.getIndex(nextNode, ListRewriteEvent.NEW);
+ } else {
+ index = -1;
+ }
+ event.insert(child, index);
+ if(child != null) {
+ this.markAsMoveOrCopyTarget(node, child);
+ }
+ }
+ }
+
+ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ if(property.isChildProperty()) {
+ NodeRewriteEvent event = getNodeEvent(node, property);
+ event.setNewValue(null);
+ } else if(property.isChildListProperty()) {
+ ListRewriteEvent event = this.getListEvent(node, property);
+ int i = event.getIndex(child, ListRewriteEvent.NEW);
+ NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
+ if(nodeEvent.getOriginalValue() == null) {
+ event.revertChange(nodeEvent);
+ } else {
+ nodeEvent.setNewValue(null);
+ }
+ }
+ }
+
+ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ if(property.isChildProperty()) {
+ NodeRewriteEvent event = getNodeEvent(node, property);
+ event.setNewValue(newChild);
+ if(newChild != null) {
+ this.markAsMoveOrCopyTarget(node, newChild);
+ }
+ } else if(property.isChildListProperty()) {
+ ListRewriteEvent event = this.getListEvent(node, property);
+ int i = event.getIndex(child, ListRewriteEvent.NEW);
+ NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
+ nodeEvent.setNewValue(newChild);
+ if(newChild != null) {
+ this.markAsMoveOrCopyTarget(node, newChild);
+ }
+ }
+ }
+
+
+ void preCloneNodeEvent(ASTNode node) {
+ this.cloneDepth++;
+ }
+
+
+ void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+ if(node.ast == root.ast && clone.ast == root.ast) {
+ if((node.getFlags() & ASTNode.ORIGINAL) != 0) {
+ this.clonedNodes.put(clone, node);
+ } else {
+ // node can be a cloned node
+ Object original = this.clonedNodes.get(node);
+ if(original != null) {
+ this.clonedNodes.put(clone, original);
+ }
+ }
+ }
+ this.cloneDepth--;
+ }
+
+ private NodeRewriteEvent getNodeEvent(ASTNode node, StructuralPropertyDescriptor property) {
+ return this.eventStore.getNodeEvent(node, property, true);
+ }
+
+ private ListRewriteEvent getListEvent(ASTNode node, StructuralPropertyDescriptor property) {
+ return this.eventStore.getListEvent(node, property, true);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JSdoc.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JSdoc.java
new file mode 100644
index 0000000..7ac64e6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JSdoc.java
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * AST node for a Javadoc-style doc comment.
+ *
+ * Javadoc:
+ * /** { TagElement } */
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class JSdoc extends Comment {
+
+ /**
+ * The "comment" structural property of this node type (JLS2 API only).
+ *
+ * @deprecated Replaced by {@link #TAGS_PROPERTY} in the JLS3 API.
+ */
+ public static final SimplePropertyDescriptor COMMENT_PROPERTY =
+ new SimplePropertyDescriptor(JSdoc.class, "comment", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "tags" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor TAGS_PROPERTY =
+ new ChildListPropertyDescriptor(JSdoc.class, "tags", TagElement.class, CYCLE_RISK); //$NON-NLS-1$
+
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(JSdoc.class, properyList);
+ addProperty(COMMENT_PROPERTY, properyList);
+ addProperty(TAGS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+ properyList = new ArrayList(2);
+ createPropertyList(JSdoc.class, properyList);
+ addProperty(TAGS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * Canonical minimal doc comment.
+ *
+ */
+ private static final String MINIMAL_DOC_COMMENT = "/** */";//$NON-NLS-1$
+
+ /**
+ * The doc comment string, including opening and closing comment
+ * delimiters; defaults to a minimal jsdoc comment.
+ * @deprecated The comment string was replaced in the 3.0 release
+ * by a representation of the structure of the doc comment.
+ * For backwards compatibility, it is still funcational as before.
+ */
+ private String comment = MINIMAL_DOC_COMMENT;
+
+ /**
+ * The list of tag elements (element type: TagElement
).
+ * Defaults to an empty list.
+ *
+ */
+ private ASTNode.NodeList tags =
+ new ASTNode.NodeList(TAGS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a doc comment owned by the given AST.
+ * The new node has an empty list of tag elements (and, for backwards
+ * compatability, an unspecified, but legal, doc comment string).
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ JSdoc(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == COMMENT_PROPERTY) {
+ if (get) {
+ return getComment();
+ } else {
+ setComment((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == TAGS_PROPERTY) {
+ return tags();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return JSDOC;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ JSdoc result = new JSdoc(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setComment(getComment());
+ }
+ result.tags().addAll(ASTNode.copySubtrees(target, tags()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.tags);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the doc comment string, including the starting
+ * and ending comment delimiters, and any embedded line breaks.
+ *
+ * @return the doc comment string
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated The comment string was replaced in the 3.0 release
+ * by a representation of the structure of the doc comment.
+ * See {@link #tags() tags}.
+ */
+ public String getComment() {
+ supportedOnlyIn2();
+ return this.comment;
+ }
+
+ /**
+ * Sets or clears the doc comment string. The documentation
+ * string must include the starting and ending comment delimiters,
+ * and any embedded line breaks.
+ *
+ * @param docComment the doc comment string
+ * @exception IllegalArgumentException if the JavaScript comment string is invalid
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated The comment string was replaced in the 3.0 release
+ * by a representation of the structure of the doc comment.
+ * See {@link #tags() tags}.
+ */
+ public void setComment(String docComment) {
+ supportedOnlyIn2();
+ if (docComment == null) {
+ throw new IllegalArgumentException();
+ }
+ char[] source = docComment.toCharArray();
+ Scanner scanner = this.ast.scanner;
+ scanner.resetTo(0, source.length);
+ scanner.setSource(source);
+ try {
+ int token;
+ boolean onlyOneComment = false;
+ while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ if (onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ onlyOneComment = true;
+ break;
+ default:
+ onlyOneComment = false;
+ }
+ }
+ if (!onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ } catch (InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(COMMENT_PROPERTY);
+ this.comment = docComment;
+ postValueChange(COMMENT_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of tag elements that make up this doc
+ * comment.
+ *
+ * The tag elements cover everything except the starting and ending
+ * comment delimiters, and generally omit leading whitespace
+ * (including a leading "*") and embedded line breaks.
+ * The first tag element of a typical doc comment represents
+ * all the material before the first explicit doc tag; this
+ * first tag element has a null
tag name and
+ * generally contains 1 or more {@link TextElement}s,
+ * and possibly interspersed with tag elements for nested tags
+ * like "{@link String String}".
+ * Subsequent tag elements represent successive top-level doc
+ * tag (e.g., "@param", "@return", "@see").
+ *
+ *
+ * Adding and removing nodes from this list affects this node
+ * dynamically.
+ *
+ *
+ * @return the live list of tag elements in this doc comment
+ * (element type: TagElement
)
+ *
+ */
+ public List tags() {
+ return this.tags;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = super.memSize() + 2 * 4;
+ if (this.comment != MINIMAL_DOC_COMMENT) {
+ // anything other than the default string takes space
+ size += stringSize(this.comment);
+ }
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.tags.listSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnit.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnit.java
new file mode 100644
index 0000000..e4ca401
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnit.java
@@ -0,0 +1,1056 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.ITypeRoot;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+/**
+ * JavaScript javaScript unit AST node type. This is the type of the root of an AST.
+ *
+ * The source range for this type of node is ordinarily the entire source file,
+ * including leading and trailing whitespace and comments.
+ *
+ * For JLS2:
+ *
+ * JavaScriptUnit:
+ * [ PackageDeclaration ]
+ * { ImportDeclaration }
+ * { TypeDeclaration | ; }
+ *
+ * For JLS3, the kinds of type declarations
+ * grew to include enum and annotation type declarations:
+ *
+ * JavaScriptUnit:
+ * [ PackageDeclaration ]
+ * { ImportDeclaration }
+ * { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | ; }
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class JavaScriptUnit extends ASTNode {
+
+ /**
+ * Canonical empty list of messages.
+ */
+ private static final Message[] EMPTY_MESSAGES = new Message[0];
+
+ /**
+ * Canonical empty list of problems.
+ */
+ private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];
+
+ /**
+ * The "imports" structural property of this node type.
+ *
+ *
+ */
+ public static final ChildListPropertyDescriptor IMPORTS_PROPERTY =
+ new ChildListPropertyDescriptor(JavaScriptUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "package" structural property of this node type.
+ *
+ *
+ */
+ public static final ChildPropertyDescriptor PACKAGE_PROPERTY =
+ new ChildPropertyDescriptor(JavaScriptUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ /**
+ * The "types" structural property of this node type.
+ *
+ *
+ */
+ public static final ChildListPropertyDescriptor TYPES_PROPERTY =
+ new ChildListPropertyDescriptor(JavaScriptUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+
+ public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(JavaScriptUnit.class, "statements", ProgramElement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ static {
+ List properyList = new ArrayList(4);
+ createPropertyList(JavaScriptUnit.class, properyList);
+ addProperty(PACKAGE_PROPERTY, properyList);
+ addProperty(IMPORTS_PROPERTY, properyList);
+ addProperty(TYPES_PROPERTY, properyList);
+ addProperty(STATEMENTS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The comment mapper, or null
if none;
+ * initially null
.
+ *
+ */
+ private DefaultCommentMapper commentMapper = null;
+
+ /**
+ * The JavaScript type root (an org.eclipse.wst.jsdt.core.IJavaScriptUnit
or an org.eclipse.wst.jsdt.core.IClassFile
)
+ * this javaScript unit was created from, or null
if it was not created from a JavaScript type root.
+ */
+ private ITypeRoot typeRoot = null;
+
+ /**
+ * The list of import declarations in textual order order;
+ * initially none (elementType: ImportDeclaration
).
+ */
+ private ASTNode.NodeList imports =
+ new ASTNode.NodeList(IMPORTS_PROPERTY);
+
+ /**
+ * Line end table. If lineEndTable[i] == p
then the
+ * line number i+1
ends at character position
+ * p
. Except for the last line, the positions are that
+ * of the last character of the line delimiter.
+ * For example, the source string A\nB\nC
has
+ * line end table {1, 3} (if \n is one character).
+ */
+ private int[] lineEndTable = Util.EMPTY_INT_ARRAY;
+
+ /**
+ * Messages reported by the validator during parsing or name resolution.
+ */
+ private Message[] messages;
+
+ /**
+ * The comment list (element type: Comment
,
+ * or null
if none; initially null
.
+ *
+ */
+ private List optionalCommentList = null;
+
+ /**
+ * The comment table, or null
if none; initially
+ * null
. This array is the storage underlying
+ * the optionalCommentList
ArrayList.
+ *
+ */
+ Comment[] optionalCommentTable = null;
+
+ /**
+ * The package declaration, or null
if none; initially
+ * null
.
+ */
+ private PackageDeclaration optionalPackageDeclaration = null;
+
+ /**
+ * Problems reported by the validator during parsing or name resolution.
+ */
+ private IProblem[] problems = EMPTY_PROBLEMS;
+
+ /**
+ * The list of type declarations in textual order order;
+ * initially none (elementType: AbstractTypeDeclaration
)
+ */
+ private ASTNode.NodeList types =
+ new ASTNode.NodeList(TYPES_PROPERTY);
+
+ private ASTNode.NodeList statements =
+ new ASTNode.NodeList(STATEMENTS_PROPERTY);
+
+
+ /**
+ * Creates a new AST node for a compilation owned by the given AST.
+ * The javaScript unit initially has no package declaration, no
+ * import declarations, and no type declarations.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ JavaScriptUnit(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getPackage());
+ acceptChildren(visitor, this.imports);
+ acceptChildren(visitor, this.types);
+ acceptChildren(visitor, this.statements);
+ }
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ JavaScriptUnit result = new JavaScriptUnit(target);
+ // n.b do not copy line number table or messages
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setPackage(
+ (PackageDeclaration) ASTNode.copySubtree(target, getPackage()));
+ result.imports().addAll(ASTNode.copySubtrees(target, imports()));
+ result.types().addAll(ASTNode.copySubtrees(target, types()));
+ result.statements().addAll(ASTNode.copySubtrees(target, statements()));
+ return result;
+ }
+
+
+ /**
+ * Returns the column number corresponding to the given source character
+ * position in the original source string. Column number are zero-based.
+ * Return -1
if it is beyond the valid range or -2
+ * if the column number information is unknown.
+ *
+ * @param position a 0-based character position, possibly
+ * negative or out of range
+ * @return the 0-based column number, or -1
if the character
+ * position does not correspond to a source line in the original
+ * source file or -2
if column number information is unknown for this
+ * javaScript unit
+ * @see ASTParser
+ *
+ */
+ public int getColumnNumber(final int position) {
+ if (this.lineEndTable == null) return -2;
+ final int line = getLineNumber(position);
+ if (line == -1) {
+ return -1;
+ }
+ if (line == 1) {
+ if (position >= getStartPosition() + getLength()) return -1;
+ return position;
+ }
+ // length is different from 0
+ int length = this.lineEndTable.length;
+ // -1 to for one-based to zero-based conversion.
+ // -1, again, to get previous line.
+ final int previousLineOffset = this.lineEndTable[line - 2];
+ // previousLineOffset + 1 is the first character of the current line
+ final int offsetForLine = previousLineOffset + 1;
+ final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line - 1];
+ if (offsetForLine > currentLineEnd) {
+ return -1;
+ } else {
+ return position - offsetForLine;
+ }
+ }
+
+ /**
+ * Finds the corresponding AST node in the given javaScript unit from
+ * which the given binding originated. Returns null
if the
+ * binding does not correspond to any node in this javaScript unit.
+ * This method always returns null
if bindings were not requested
+ * when this AST was built.
+ *
+ * The following table indicates the expected node type for the various
+ * different kinds of bindings:
+ *
+ * - package - a
PackageDeclaration
+ * - class or interface - a
TypeDeclaration
or a
+ * AnonymousClassDeclaration
(for anonymous classes)
+ * - primitive type - none
+ * - array type - none
+ * - field - a
VariableDeclarationFragment
in a
+ * FieldDeclaration
+ * - local variable - a
SingleVariableDeclaration
, or
+ * a VariableDeclarationFragment
in a
+ * VariableDeclarationStatement
or
+ * VariableDeclarationExpression
+ * - method - a
FunctionDeclaration
+ * - constructor - a
FunctionDeclaration
+ * - annotation type - an
AnnotationTypeDeclaration
+ * - annotation type member - an
AnnotationTypeMemberDeclaration
+ * - enum type - an
EnumDeclaration
+ * - enum constant - an
EnumConstantDeclaration
+ * - type variable - a
TypeParameter
+ * - capture binding - none
+ * - annotation binding - an
Annotation
+ * - member value pair binding - an
MemberValuePair
,
+ * or null
if it represents a default value or a single member value
+ *
+ * For parameterized or raw type bindings, the declaring node is
+ * that of the corresponding generic type. And for parameterized or raw
+ * method bindings, the declaring node is that of the corresponding
+ * generic method.
+ *
+ *
+ * Each call to {@link ASTParser#createAST(org.eclipse.core.runtime.IProgressMonitor)} with a request for bindings
+ * gives rise to separate universe of binding objects. This method always returns
+ * null
when the binding object comes from a different AST.
+ * Use findDeclaringNode(binding.getKey())
when the binding comes
+ * from a different AST.
+ *
+ *
+ * @param binding the binding
+ * @return the corresponding node where the given binding is declared,
+ * or null
if the binding does not correspond to a node in this
+ * javaScript unit or if bindings were not requested when this AST was built
+ * @see #findDeclaringNode(String)
+ */
+ public ASTNode findDeclaringNode(IBinding binding) {
+ return this.ast.getBindingResolver().findDeclaringNode(binding);
+ }
+
+ /**
+ * Finds the corresponding AST node in the given javaScript unit from
+ * which the binding with the given key originated. Returns
+ * null
if the corresponding node cannot be determined.
+ * This method always returns null
if bindings were not requested
+ * when this AST was built.
+ *
+ * The following table indicates the expected node type for the various
+ * different kinds of binding keys:
+ *
+ *
+ * - package - a
PackageDeclaration
+ * - class or interface - a
TypeDeclaration
or a
+ * AnonymousClassDeclaration
(for anonymous classes)
+ * - primitive type - none
+ * - array type - none
+ * - field - a
VariableDeclarationFragment
in a
+ * FieldDeclaration
+ * - local variable - a
SingleVariableDeclaration
, or
+ * a VariableDeclarationFragment
in a
+ * VariableDeclarationStatement
or
+ * VariableDeclarationExpression
+ * - method - a
FunctionDeclaration
+ * - constructor - a
FunctionDeclaration
+ * - annotation type - an
AnnotationTypeDeclaration
+ * - annotation type member - an
AnnotationTypeMemberDeclaration
+ * - enum type - an
EnumDeclaration
+ * - enum constant - an
EnumConstantDeclaration
+ * - type variable - a
TypeParameter
+ * - capture binding - none
+ *
+ * For parameterized or raw type bindings, the declaring node is
+ * that of the corresponding generic type. And for parameterized or raw
+ * method bindings, the declaring node is that of the corresponding
+ * generic method.
+ *
+ *
+ * @param key the binding key, or null
+ * @return the corresponding node where a binding with the given
+ * key is declared, or null
if the key is null
+ * or if the key does not correspond to a node in this javaScript unit
+ * or if bindings were not requested when this AST was built
+ * @see IBinding#getKey()
+ *
+ */
+ public ASTNode findDeclaringNode(String key) {
+ return this.ast.getBindingResolver().findDeclaringNode(key);
+ }
+
+ /**
+ * Returns a list of the comments encountered while parsing
+ * this javaScript unit.
+ *
+ * Since the JavaScript language allows comments to appear most anywhere
+ * in the source text, it is problematic to locate comments in relation
+ * to the structure of an AST. The one exception is doc comments
+ * which, by convention, immediately precede type, field, and
+ * method declarations; these comments are located in the AST
+ * by {@link BodyDeclaration#getjsdoc BodyDeclaration.getJavadoc}.
+ * Other comments do not show up in the AST. The table of comments
+ * is provided for clients that need to find the source ranges of
+ * all comments in the original source string. It includes entries
+ * for comments of all kinds (line, block, and doc), arranged in order
+ * of increasing source position.
+ *
+ *
+ * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
+ * of a doc comment associated with a body declaration is the body
+ * declaration node; for these comment nodes
+ * {@link ASTNode#getRoot() getRoot()} will return the javaScript unit
+ * (assuming an unmodified AST) reflecting the fact that these nodes
+ * are property located in the AST for the javaScript unit.
+ * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
+ * will return null
, and {@link ASTNode#getRoot() getRoot()}
+ * will return the comment node itself, indicating that these comment nodes
+ * are not directly connected to the AST for the javaScript unit. The
+ * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
+ * method provides a way to navigate from a comment to its compilation
+ * unit.
+ *
+ *
+ * A note on visitors: The only comment nodes that will be visited when
+ * visiting a javaScript unit are the doc comments parented by body
+ * declarations. To visit all comments in normal reading order, iterate
+ * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
+ * on each element.
+ *
+ *
+ * Clients cannot modify the resulting list.
+ *
+ *
+ * @return an unmodifiable list of comments in increasing order of source
+ * start position, or null
if comment information
+ * for this javaScript unit is not available
+ * @see ASTParser
+ *
+ */
+ public List getCommentList() {
+ return this.optionalCommentList;
+ }
+
+ /**
+ * Returns the internal comment mapper.
+ *
+ * @return the comment mapper, or null
if none.
+ *
+ */
+ DefaultCommentMapper getCommentMapper() {
+ return this.commentMapper;
+ }
+
+ /**
+ * Returns the extended source length of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return a (possibly 0) length, or 0
+ * if no source position information is recorded for this node
+ * @see #getExtendedStartPosition(ASTNode)
+ *
+ */
+ public int getExtendedLength(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ // fall back: use best info available
+ return node.getLength();
+ } else {
+ return this.commentMapper.getExtendedLength(node);
+ }
+ }
+
+ /**
+ * Returns the extended start position of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * @param node the node
+ * @return the 0-based character index, or -1
+ * if no source position information is recorded for this node
+ * @see #getExtendedLength(ASTNode)
+ *
+ */
+ public int getExtendedStartPosition(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ // fall back: use best info available
+ return node.getStartPosition();
+ } else {
+ return this.commentMapper.getExtendedStartPosition(node);
+ }
+ }
+
+ /**
+ * The JavaScript element (an org.eclipse.wst.jsdt.core.IJavaScriptUnit
or an org.eclipse.wst.jsdt.core.IClassFile
)
+ * this javaScript unit was created from, or null
if it was not created from a JavaScript element.
+ *
+ * @return the JavaScript element this javaScript unit was created from, or null
if none
+ *
+ * @see #getTypeRoot()
+ */
+ public IJavaScriptElement getJavaElement() {
+ return this.typeRoot;
+ }
+
+ /**
+ * Returns the list of messages reported by the validator during the parsing
+ * or the type checking of this javaScript unit. This list might be a subset of
+ * errors detected and reported by a JavaScript compiler.
+ *
+ * This list of messages is suitable for simple clients that do little
+ * more than log the messages or display them to the user. Clients that
+ * need further details should call getProblems
to get
+ * validator problem objects.
+ *
+ *
+ * @return the list of messages, possibly empty
+ * @see #getProblems()
+ * @see ASTParser
+ */
+ public Message[] getMessages() {
+ if (this.messages == null) {
+ int problemLength = this.problems.length;
+ if (problemLength == 0) {
+ this.messages = EMPTY_MESSAGES;
+ } else {
+ this.messages = new Message[problemLength];
+ for (int i = 0; i < problemLength; i++) {
+ IProblem problem = this.problems[i];
+ int start = problem.getSourceStart();
+ int end = problem.getSourceEnd();
+ messages[i] = new Message(problem.getMessage(), start, end - start + 1);
+ }
+ }
+ }
+ return this.messages;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return JAVASCRIPT_UNIT;
+ }
+
+ /**
+ * Returns the node for the package declaration of this compilation
+ * unit, or null
if this javaScript unit is in the
+ * default package.
+ *
+ * @return the package declaration node, or null
if none
+ */
+ public PackageDeclaration getPackage() {
+ return this.optionalPackageDeclaration;
+ }
+
+ /**
+ * Given a line number and column number, returns the corresponding
+ * position in the original source string.
+ * Returns -2 if no line number information is available for this
+ * javaScript unit.
+ * Returns the total size of the source string if line
+ * is greater than the actual number lines in the unit.
+ * Returns -1 if column
is less than 0,
+ * or the position of the last character of the line if column
+ * is beyond the legal range, or the given line number is less than one.
+ *
+ * @param line the one-based line number
+ * @param column the zero-based column number
+ * @return the 0-based character position in the source string;
+ * -2
if line/column number information is not known
+ * for this javaScript unit or -1
the inputs are not valid
+ *
+ */
+ public int getPosition(int line, int column) {
+ if (this.lineEndTable == null) return -2;
+ if (line < 1 || column < 0) return -1;
+ int length;
+ if ((length = this.lineEndTable.length) == 0) {
+ if (line != 1) return -1;
+ return column >= getStartPosition() + getLength() ? -1 : column;
+ }
+ if (line == 1) {
+ final int endOfLine = this.lineEndTable[0];
+ return column > endOfLine ? -1 : column;
+ } else if( line > length + 1 ) {
+ // greater than the number of lines in the source string.
+ return -1;
+ }
+ // -1 to for one-based to zero-based conversion.
+ // -1, again, to get previous line.
+ final int previousLineOffset = this.lineEndTable[line - 2];
+ // previousLineOffset + 1 is the first character of the current line
+ final int offsetForLine = previousLineOffset + 1;
+ final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line-1];
+ if ((offsetForLine + column) > currentLineEnd) {
+ return -1;
+ } else {
+ return offsetForLine + column;
+ }
+ }
+
+ /**
+ * Returns the list of detailed problem reports noted by the compiler
+ * during the parsing or the type checking of this javaScript unit. This
+ * list might be a subset of errors detected and reported by a Java
+ * compiler.
+ *
+ * Simple clients that do little more than log the messages or display
+ * them to the user should probably call getMessages
instead.
+ *
+ *
+ * @return the list of detailed problem objects, possibly empty
+ * @see #getMessages()
+ * @see ASTParser
+ *
+ */
+ public IProblem[] getProblems() {
+ return this.problems;
+ }
+
+ /**
+ * The JavaScript type root (a {@link org.eclipse.wst.jsdt.core.IJavaScriptUnit javaScript unit} or a {@link org.eclipse.wst.jsdt.core.IClassFile class file})
+ * this javaScript unit was created from, or null
if it was not created from a JavaScript type root.
+ *
+ * @return the JavaScript type root this javaScript unit was created from, or null
if none
+ *
+ */
+ public ITypeRoot getTypeRoot() {
+ return this.typeRoot;
+ }
+
+ /**
+ * Returns the live list of nodes for the import declarations of this
+ * javaScript unit, in order of appearance.
+ *
+ * @return the live list of import declaration nodes
+ * (elementType: ImportDeclaration
)
+ */
+ public List imports() {
+ return this.imports;
+ }
+
+ /**
+ * Return the index in the whole comments list {@link #getCommentList() }
+ * of the first leading comments associated with the given node.
+ *
+ * @param node the node
+ * @return 0-based index of first leading comment or -1 if node has no associated
+ * comment before its start position.
+ *
+ */
+ public int firstLeadingCommentIndex(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ return -1;
+ }
+ return this.commentMapper.firstLeadingCommentIndex(node);
+ }
+
+ /**
+ * Return the index in the whole comments list {@link #getCommentList() }
+ * of the last trailing comments associated with the given node.
+ *
+ * @param node the node
+ * @return 0-based index of last trailing comment or -1 if node has no
+ * associated comment after its end position.
+ *
+ */
+ public int lastTrailingCommentIndex(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ if (this.commentMapper == null || node.getAST() != getAST()) {
+ return -1;
+ }
+ return this.commentMapper.lastTrailingCommentIndex(node);
+ }
+
+ /**
+ * Initializes the internal comment mapper with the given
+ * scanner.
+ *
+ * @param scanner the scanner
+ *
+ */
+ void initCommentMapper(Scanner scanner) {
+ this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
+ this.commentMapper.initialize(this, scanner);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == IMPORTS_PROPERTY) {
+ return imports();
+ }
+ if (property == TYPES_PROPERTY) {
+ return types();
+ }
+ if (property == STATEMENTS_PROPERTY) {
+ return statements();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == PACKAGE_PROPERTY) {
+ if (get) {
+ return getPackage();
+ } else {
+ setPackage((PackageDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /**
+ * Returns the line number corresponding to the given source character
+ * position in the original source string. The initial line of the
+ * javaScript unit is numbered 1, and each line extends through the
+ * last character of the end-of-line delimiter. The very last line extends
+ * through the end of the source string and has no line delimiter.
+ * For example, the source string class A\n{\n}
has 3 lines
+ * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
+ * Returns -1 for a character position that does not correspond to any
+ * source line, or -2 if no line number information is available for this
+ * javaScript unit.
+ *
+ * @param position a 0-based character position, possibly
+ * negative or out of range
+ * @return the 1-based line number, or -1
if the character
+ * position does not correspond to a source line in the original
+ * source file or -2
if line number information is not known for this
+ * javaScript unit
+ * @see ASTParser
+ *
+ */
+ public int getLineNumber(int position) {
+ if (this.lineEndTable == null) return -2;
+ int length;
+ if ((length = this.lineEndTable.length) == 0) {
+ if (position >= getStartPosition() + getLength()) {
+ return -1;
+ }
+ return 1;
+ }
+ int low = 0;
+ if (position < 0) {
+ // position illegal
+ return -1;
+ }
+ if (position <= this.lineEndTable[low]) {
+ // before the first line delimiter
+ return 1;
+ }
+ // assert position > lineEndTable[low+1] && low == 0
+ int hi = length - 1;
+ if (position > this.lineEndTable[hi]) {
+ // position beyond the last line separator
+ if (position >= getStartPosition() + getLength()) {
+ // this is beyond the end of the source length
+ return -1;
+ } else {
+ return length + 1;
+ }
+ }
+ // assert lineEndTable[low] < position <= lineEndTable[hi]
+ // && low == 0 && hi == length - 1 && low < hi
+
+ // binary search line end table
+ while (true) {
+ // invariant lineEndTable[low] < position <= lineEndTable[hi]
+ // && 0 <= low < hi <= length - 1
+ // reducing measure hi - low
+ if (low + 1 == hi) {
+ // assert lineEndTable[low] < position <= lineEndTable[low+1]
+ // position is on line low+1 (line number is low+2)
+ return low + 2;
+ }
+ // assert hi - low >= 2, so average is truly in between
+ int mid = low + (hi - low) / 2;
+ // assert 0 <= low < mid < hi <= length - 1
+ if (position <= this.lineEndTable[mid]) {
+ // assert lineEndTable[low] < position <= lineEndTable[mid]
+ // && 0 <= low < mid < hi <= length - 1
+ hi = mid;
+ } else {
+ // position > lineEndTable[mid]
+ // assert lineEndTable[mid] < position <= lineEndTable[hi]
+ // && 0 <= low < mid < hi <= length - 1
+ low = mid;
+ }
+ // in both cases, invariant reachieved with reduced measure
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 8 * 4;
+ if (this.lineEndTable != null) {
+ size += HEADERS + 4 * this.lineEndTable.length;
+ }
+ if (this.optionalCommentTable != null) {
+ size += HEADERS + 4 * this.optionalCommentTable.length;
+ }
+ // ignore the space taken up by optionalCommentList
+ return size;
+ }
+
+ /**
+ * Enables the recording of changes to this compilation
+ * unit and its descendents. The javaScript unit must have
+ * been created by ASTParser
and still be in
+ * its original state. Once recording is on,
+ * arbitrary changes to the subtree rooted at this compilation
+ * unit are recorded internally. Once the modification has
+ * been completed, call rewrite
to get an object
+ * representing the corresponding edits to the original
+ * source code string.
+ *
+ * @exception IllegalArgumentException if this javaScript unit is
+ * marked as unmodifiable, or if this javaScript unit has already
+ * been tampered with, or recording has already been enabled
+ *
+ */
+ public void recordModifications() {
+ getAST().recordModifications(this);
+ }
+
+ /**
+ * Converts all modifications recorded for this compilation
+ * unit into an object representing the corresponding text
+ * edits to the given document containing the original source
+ * code for this javaScript unit.
+ *
+ * The javaScript unit must have been created by
+ * ASTParser
from the source code string in the
+ * given document, and recording must have been turned
+ * on with a prior call to recordModifications
+ * while the AST was still in its original state.
+ *
+ *
+ * Calling this methods does not discard the modifications
+ * on record. Subsequence modifications made to the AST
+ * are added to the ones already on record. If this method
+ * is called again later, the resulting text edit object will
+ * accurately reflect the net cumulative affect of all those
+ * changes.
+ *
+ *
+ * @param document original document containing source code
+ * for this javaScript unit
+ * @param options the table of formatter options
+ * (key type: String
; value type: String
);
+ * or null
to use the standard global options
+ * {@link org.eclipse.wst.jsdt.core.JavaScriptCore#getOptions() JavaScriptCore.getOptions()}.
+ * @return text edit object describing the changes to the
+ * document corresponding to the recorded AST modifications
+ * @exception IllegalArgumentException if the document passed is
+ * null
or does not correspond to this AST
+ * @exception IllegalStateException if recordModifications
+ * was not called to enable recording
+ * @see #recordModifications()
+ *
+ */
+ public TextEdit rewrite(IDocument document, Map options) {
+ return getAST().rewrite(document, options);
+ }
+
+ /**
+ * Sets the list of the comments encountered while parsing
+ * this javaScript unit.
+ *
+ * @param commentTable a list of comments in increasing order
+ * of source start position, or null
if comment
+ * information for this javaScript unit is not available
+ * @exception IllegalArgumentException if the comment table is
+ * not in increasing order of source position
+ * @see #getCommentList()
+ * @see ASTParser
+ *
+ */
+ void setCommentTable(Comment[] commentTable) {
+ // double check table to ensure that all comments have
+ // source positions and are in strictly increasing order
+ if (commentTable == null) {
+ this.optionalCommentList = null;
+ this.optionalCommentTable = null;
+ } else {
+ int nextAvailablePosition = 0;
+ for (int i = 0; i < commentTable.length; i++) {
+ Comment comment = commentTable[i];
+ if (comment == null) {
+ throw new IllegalArgumentException();
+ }
+ int start = comment.getStartPosition();
+ int length = comment.getLength();
+ if (start < 0 || length < 0 || start < nextAvailablePosition) {
+ throw new IllegalArgumentException();
+ }
+ nextAvailablePosition = comment.getStartPosition() + comment.getLength();
+ }
+ this.optionalCommentTable = commentTable;
+ List commentList = Arrays.asList(commentTable);
+ // protect the list from further modification
+ this.optionalCommentList = Collections.unmodifiableList(commentList);
+ }
+ }
+
+ /**
+ * Sets the JavaScript type root (a {@link org.eclipse.wst.jsdt.core.IJavaScriptUnit javaScript unit} or a {@link org.eclipse.wst.jsdt.core.IClassFile class file})
+ * this javaScript unit was created from, or null
if it was not created from a JavaScript type root.
+ *
+ * @param typeRoot the JavaScript type root this javaScript unit was created from
+ */
+ void setTypeRoot(ITypeRoot typeRoot) {
+ this.typeRoot = typeRoot;
+ }
+
+ /**
+ * Sets the line end table for this javaScript unit.
+ * If lineEndTable[i] == p
then line number i+1
+ * ends at character position p
. Except for the last line, the
+ * positions are that of (the last character of) the line delimiter.
+ * For example, the source string A\nB\nC
has
+ * line end table {1, 3, 4}.
+ *
+ * @param lineEndTable the line end table
+ */
+ void setLineEndTable(int[] lineEndTable) {
+ if (lineEndTable == null) {
+ throw new NullPointerException();
+ }
+ // alternate root is *not* considered a structural property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.lineEndTable = lineEndTable;
+ }
+
+ /**
+ * Sets or clears the package declaration of this javaScript unit
+ * node to the given package declaration node.
+ *
+ * @param pkgDecl the new package declaration node, or
+ * null
if this javaScript unit does not have a package
+ * declaration (that is in the default package)
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setPackage(PackageDeclaration pkgDecl) {
+ ASTNode oldChild = this.optionalPackageDeclaration;
+ preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+ this.optionalPackageDeclaration = pkgDecl;
+ postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+ }
+
+
+ /**
+ * Sets the array of problems reported by the validator during the parsing or
+ * name resolution of this javaScript unit.
+ *
+ * @param problems the list of problems
+ */
+ void setProblems(IProblem[] problems) {
+ if (problems == null) {
+ throw new IllegalArgumentException();
+ }
+ this.problems = problems;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ int size = memSize();
+ if (this.optionalPackageDeclaration != null) {
+ size += getPackage().treeSize();
+ }
+ size += this.imports.listSize();
+ size += this.types.listSize();
+ size += this.statements.listSize();
+ // include disconnected comments
+ if (this.optionalCommentList != null) {
+ for (int i = 0; i < this.optionalCommentList.size(); i++) {
+ Comment comment = (Comment) this.optionalCommentList.get(i);
+ if (comment != null && comment.getParent() == null) {
+ size += comment.treeSize();
+ }
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the live list of nodes for the top-level type declarations of this
+ * javaScript unit, in order of appearance.
+ *
+ * Note that in JLS3, the types may include both enum declarations
+ * and annotation type declarations introduced in J2SE 5.
+ * For JLS2, the elements are always TypeDeclaration
.
+ *
+ *
+ * @return the live list of top-level type declaration
+ * nodes (elementType: AbstractTypeDeclaration
)
+ */
+ public List types() {
+ return this.types;
+ }
+
+ public List statements() {
+ return this.statements;
+ }
+
+ public ITypeBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnitBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnitBinding.java
new file mode 100644
index 0000000..71823f2
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnitBinding.java
@@ -0,0 +1,749 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.jsdt.core.IClassFile;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.IPackageFragment;
+import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.IDependent;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.core.ClassFile;
+import org.eclipse.wst.jsdt.internal.core.JavaElement;
+
+/**
+ * Internal implementation of type bindings.
+ */
+class JavaScriptUnitBinding implements ITypeBinding {
+ private static final IFunctionBinding[] NO_METHOD_BINDINGS = new IFunctionBinding[0];
+
+ private static final String NO_NAME = ""; //$NON-NLS-1$
+ private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+ private static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
+
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding;
+ private String key;
+ private BindingResolver resolver;
+
+ public JavaScriptUnitBinding(BindingResolver resolver, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding) {
+ this.binding = binding;
+ this.resolver = resolver;
+ }
+
+ public ITypeBinding createArrayType(int dimension) {
+// int realDimensions = dimension;
+// realDimensions += this.getDimensions();
+// if (realDimensions < 1 || realDimensions > 255) {
+// throw new IllegalArgumentException();
+// }
+// return this.resolver.resolveArrayType(this, dimension);
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getBinaryName()
+ *
+ */
+ public String getBinaryName() {
+ char[] constantPoolName = this.binding.constantPoolName();
+ if (constantPoolName == null) return null;
+ char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
+ return new String(dotSeparated);
+ }
+
+ /*
+ * Returns the class file for the given file name, or null if not found.
+ * @see org.eclipse.wst.jsdt.internal.compiler.env.IDependent#getFileName()
+ */
+// private IClassFile getClassFile(char[] fileName) {
+// int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+// int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
+// if (pkgEnd == -1)
+// pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
+// if (jarSeparator != -1 && pkgEnd < jarSeparator) // if in a jar and no slash, it is a default package -> pkgEnd should be equal to jarSeparator
+// pkgEnd = jarSeparator;
+// if (pkgEnd == -1)
+// return null;
+// IPackageFragment pkg = getPackageFragment(fileName, pkgEnd, jarSeparator);
+// if (pkg == null) return null;
+// int start;
+// return pkg.getClassFile(new String(fileName, start = pkgEnd + 1, fileName.length - start));
+// }
+
+ /*
+ * Returns the javaScript unit for the given file name, or null if not found.
+ * @see org.eclipse.wst.jsdt.internal.compiler.env.IDependent#getFileName()
+ */
+ private IJavaScriptUnit getCompilationUnit(char[] fileName) {
+ char[] slashSeparatedFileName = CharOperation.replaceOnCopy(fileName, File.separatorChar, '/');
+ int pkgEnd = CharOperation.lastIndexOf('/', slashSeparatedFileName); // pkgEnd is exclusive
+ if (pkgEnd == -1)
+ return null;
+ IPackageFragment pkg = getPackageFragment(slashSeparatedFileName, pkgEnd, -1/*no jar separator for .js files*/);
+ if (pkg == null) return null;
+ int start;
+ IJavaScriptUnit cu = pkg.getJavaScriptUnit(new String(slashSeparatedFileName, start = pkgEnd+1, slashSeparatedFileName.length - start));
+ if (this.resolver instanceof DefaultBindingResolver) {
+ IJavaScriptUnit workingCopy = cu.findWorkingCopy(((DefaultBindingResolver) this.resolver).workingCopyOwner);
+ if (workingCopy != null)
+ return workingCopy;
+ }
+ return cu;
+ }
+
+ /*
+ * @see ITypeBinding#getComponentType()
+ */
+ public ITypeBinding getComponentType() {
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredFields()
+ */
+ public IVariableBinding[] getDeclaredFields() {
+ try {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ FieldBinding[] fields = referenceBinding.fields();
+ int length = fields.length;
+ IVariableBinding[] newFields = new IVariableBinding[length];
+ for (int i = 0; i < length; i++) {
+ newFields[i] = this.resolver.getVariableBinding(fields[i]);
+ }
+ return newFields;
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ }
+ return NO_VARIABLE_BINDINGS;
+ }
+
+
+ /*
+ * @see ITypeBinding#getDeclaredMethods()
+ */
+ public IFunctionBinding[] getDeclaredMethods() {
+ try {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding[] methods = referenceBinding.methods();
+ int length = methods.length;
+ IFunctionBinding[] newMethods = new IFunctionBinding[length];
+ for (int i = 0; i < length; i++) {
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding = methods[i];
+// if (!shouldBeRemoved(methodBinding)) {
+ newMethods[i] = this.resolver.getMethodBinding(methodBinding);
+// }
+ }
+ return newMethods;
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ }
+ return NO_METHOD_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredModifiers()
+ */
+ public int getDeclaredModifiers() {
+ return getModifiers();
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredTypes()
+ */
+ public ITypeBinding[] getDeclaredTypes() {
+
+ return NO_TYPE_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaringMethod()
+ */
+ public IFunctionBinding getDeclaringMethod() {
+
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDimensions()
+ */
+ public int getDimensions() {
+ return 0;
+ }
+
+ /*
+ * @see ITypeBinding#getElementType()
+ */
+ public ITypeBinding getElementType() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeDeclaration()
+ */
+ public ITypeBinding getTypeDeclaration() {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getErasure()
+ */
+ public ITypeBinding getErasure() {
+ return this.resolver.getTypeBinding(this.binding);
+ }
+
+ public ITypeBinding[] getInterfaces() {
+// if (this.binding == null)
+ return NO_TYPE_BINDINGS;
+// switch (this.binding.kind()) {
+// case Binding.ARRAY_TYPE :
+// case Binding.BASE_TYPE :
+// return NO_TYPE_BINDINGS;
+// }
+// ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+// ReferenceBinding[] interfaces = null;
+// try {
+// interfaces = referenceBinding.superInterfaces();
+// } catch (RuntimeException e) {
+// /* in case a method cannot be resolvable due to missing jars on the includepath
+// * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+// * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+// * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+// */
+// }
+// if (interfaces == null) {
+// return NO_TYPE_BINDINGS;
+// }
+// int length = interfaces.length;
+// if (length == 0) {
+// return NO_TYPE_BINDINGS;
+// } else {
+// ITypeBinding[] newInterfaces = new ITypeBinding[length];
+// for (int i = 0; i < length; i++) {
+// ITypeBinding typeBinding = this.resolver.getTypeBinding(interfaces[i]);
+// if (typeBinding == null) {
+// return NO_TYPE_BINDINGS;
+// }
+// newInterfaces[i] = typeBinding;
+// }
+// return newInterfaces;
+// }
+ }
+
+ public IJavaScriptElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element == null)
+ return null;
+ return element.resolved(this.binding);
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ return getUnresolvedJavaElement(this.binding);
+ }
+ private JavaElement getUnresolvedJavaElement(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding typeBinding ) {
+ if (typeBinding == null)
+ return null;
+
+ ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+ char[] fileName = referenceBinding.getFileName();
+ if (fileName == null) return null; // case of a WilCardBinding that doesn't have a corresponding JavaScript element
+ // member or top level type
+ ITypeBinding declaringTypeBinding = getDeclaringClass();
+ if (declaringTypeBinding == null) {
+ // top level type
+ if (((ReferenceBinding)this.binding).isBinaryBinding()) {
+ ClassFile classFile = (ClassFile) getClassFile(fileName);
+ return classFile;
+ }
+ IJavaScriptUnit cu = getCompilationUnit(fileName);
+ return (JavaElement)cu;
+ } else {
+ // member type
+ IType declaringType = (IType) declaringTypeBinding.getJavaElement();
+ if (declaringType == null) return null;
+ return (JavaElement) declaringType.getType(new String(referenceBinding.sourceName()));
+ }
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.TYPE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ if (referenceBinding.isAnonymousType()) {
+ return accessFlags & ~Modifier.FINAL;
+ }
+ return accessFlags;
+ } else if (isAnnotation()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ // clear the AccAbstract, AccAnnotation and the AccInterface bits
+ return accessFlags & ~(ClassFileConstants.AccAbstract);
+ } else if (isInterface()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ // clear the AccAbstract and the AccInterface bits
+ return accessFlags & ~(ClassFileConstants.AccAbstract);
+ } else {
+ return 0;
+ }
+ }
+
+ public String getName() {
+ return new String(this.binding.sourceName());
+ }
+
+ /*
+ * @see ITypeBinding#getPackage()
+ */
+ public IPackageBinding getPackage() {
+ switch (this.binding.kind()) {
+ case Binding.BASE_TYPE :
+ case Binding.ARRAY_TYPE :
+ return null;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return this.resolver.getPackageBinding(referenceBinding.getPackage());
+ }
+
+ /*
+ * Returns the package that includes the given file name, or null if not found.
+ * pkgEnd == jarSeparator if default package in a jar
+ * pkgEnd > jarSeparator if non default package in a jar
+ * pkgEnd > 0 if package not in a jar
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.env.IDependent#getFileName()
+ */
+ private IPackageFragment getPackageFragment(char[] fileName, int pkgEnd, int jarSeparator) {
+ if (jarSeparator != -1) {
+ String jarMemento = new String(fileName, 0, jarSeparator);
+ IPackageFragmentRoot root = (IPackageFragmentRoot) JavaScriptCore.create(jarMemento);
+ if (pkgEnd == jarSeparator)
+ return root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ char[] pkgName = CharOperation.subarray(fileName, jarSeparator+1, pkgEnd);
+ CharOperation.replace(pkgName, '/', '.');
+ return root.getPackageFragment(new String(pkgName));
+ } else {
+ Path path = new Path(new String(fileName, 0, pkgEnd));
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IContainer folder = path.segmentCount() == 1 ? workspaceRoot.getProject(path.lastSegment()) : (IContainer) workspaceRoot.getFolder(path);
+ IJavaScriptElement element = JavaScriptCore.create(folder);
+ if (element == null) return null;
+ switch (element.getElementType()) {
+ case IJavaScriptElement.PACKAGE_FRAGMENT:
+ return (IPackageFragment) element;
+ case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT:
+ return ((IPackageFragmentRoot) element).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ case IJavaScriptElement.JAVASCRIPT_PROJECT:
+ IPackageFragmentRoot root = ((IJavaScriptProject) element).getPackageFragmentRoot(folder);
+ if (root == null) return null;
+ return root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getQualifiedName()
+ */
+ public String getQualifiedName() {
+ StringBuffer buffer;
+// switch (this.binding.kind()) {
+//
+// case Binding.RAW_TYPE :
+// return getTypeDeclaration().getQualifiedName();
+//
+// case Binding.ARRAY_TYPE :
+// ITypeBinding elementType = getElementType();
+// if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
+// return NO_NAME;
+// }
+// final int dimensions = getDimensions();
+// char[] brackets = new char[dimensions * 2];
+// for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+// brackets[i] = ']';
+// brackets[i - 1] = '[';
+// }
+// buffer = new StringBuffer(elementType.getQualifiedName());
+// buffer.append(brackets);
+// return String.valueOf(buffer);
+//
+// case Binding.TYPE_PARAMETER :
+// if (isCapture()) {
+// return NO_NAME;
+// }
+// TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+// return new String(typeVariableBinding.sourceName);
+//
+// case Binding.PARAMETERIZED_TYPE :
+// buffer = new StringBuffer();
+// if (isMember()) {
+// buffer
+// .append(getDeclaringClass().getQualifiedName())
+// .append('.');
+// ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+// buffer.append(parameterizedTypeBinding.sourceName());
+// ITypeBinding[] typeArguments = getTypeArguments();
+// final int typeArgumentsLength = typeArguments.length;
+// if (typeArgumentsLength != 0) {
+// buffer.append('<');
+// for (int i = 0, max = typeArguments.length; i < max; i++) {
+// if (i > 0) {
+// buffer.append(',');
+// }
+// buffer.append(typeArguments[i].getQualifiedName());
+// }
+// buffer.append('>');
+// }
+// return String.valueOf(buffer);
+// }
+// buffer.append(getTypeDeclaration().getQualifiedName());
+// ITypeBinding[] typeArguments = getTypeArguments();
+// final int typeArgumentsLength = typeArguments.length;
+// if (typeArgumentsLength != 0) {
+// buffer.append('<');
+// for (int i = 0, max = typeArguments.length; i < max; i++) {
+// if (i > 0) {
+// buffer.append(',');
+// }
+// buffer.append(typeArguments[i].getQualifiedName());
+// }
+// buffer.append('>');
+// }
+// return String.valueOf(buffer);
+//
+// default :
+ if (isAnonymous() || isLocal()) {
+ return NO_NAME;
+ }
+ if (isPrimitive() || isNullType()) {
+ BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+ return new String(baseTypeBinding.simpleName);
+ }
+ if (isMember()) {
+ buffer = new StringBuffer();
+ buffer
+ .append(getDeclaringClass().getQualifiedName())
+ .append('.');
+ buffer.append(getName());
+ return String.valueOf(buffer);
+ }
+ PackageBinding packageBinding = this.binding.getPackage();
+ buffer = new StringBuffer();
+ if (packageBinding != null && packageBinding.compoundName != CharOperation.NO_CHAR_CHAR) {
+ buffer.append(CharOperation.concatWith(packageBinding.compoundName, '.')).append('.');
+ }
+ buffer.append(getName());
+ return String.valueOf(buffer);
+// }
+ }
+
+ /*
+ * @see ITypeBinding#getSuperclass()
+ */
+ public ITypeBinding getSuperclass() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeArguments()
+ */
+ public ITypeBinding[] getTypeArguments() {
+ return NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeBounds()
+ */
+ public ITypeBinding[] getTypeBounds() {
+ return NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeParameters()
+ */
+ public ITypeBinding[] getTypeParameters() {
+ return NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isGenericType()
+ *
+ */
+ public boolean isGenericType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isAnonymous()
+ */
+ public boolean isAnonymous() {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isArray()
+ */
+ public boolean isArray() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
+ */
+ public boolean isAssignmentCompatible(ITypeBinding type) {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isCapture()
+ */
+ public boolean isCapture() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isCastCompatible(ITypeBinding)
+ */
+ public boolean isCastCompatible(ITypeBinding type) {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isClass()
+ */
+ public boolean isClass() {
+ return this.binding.isClass();
+ }
+
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ if (isClass() || isInterface() || isEnum()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isDeprecated();
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isEnum()
+ */
+ public boolean isEnum() {
+ return false;
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ *
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof JavaScriptUnitBinding)) {
+ return false;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding otherBinding = ((JavaScriptUnitBinding) other).binding;
+ // check return type
+ return BindingComparator.isEqual(this.binding, otherBinding);
+ }
+
+ /*
+ * @see ITypeBinding#isFromSource()
+ */
+ public boolean isFromSource() {
+ return !((ReferenceBinding)this.binding).isBinaryBinding();
+ }
+
+ /*
+ * @see ITypeBinding#isInterface()
+ */
+ public boolean isInterface() {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isLocal()
+ */
+ public boolean isLocal() {
+ return true;
+ }
+
+ /*
+ * @see ITypeBinding#isMember()
+ */
+ public boolean isMember() {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isNested()
+ */
+ public boolean isNested() {
+ return false;
+ }
+
+ /**
+ * @see ITypeBinding#isNullType()
+ */
+ public boolean isNullType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isParameterizedType()
+ */
+ public boolean isParameterizedType() {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isPrimitive()
+ */
+ public boolean isPrimitive() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isRawType()
+ */
+ public boolean isRawType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isSubTypeCompatible(ITypeBinding)
+ */
+ public boolean isSubTypeCompatible(ITypeBinding type) {
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isTopLevel()
+ */
+ public boolean isTopLevel() {
+ return true;
+ }
+
+ /*
+ * @see ITypeBinding#isTypeVariable()
+ */
+ public boolean isTypeVariable() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isUpperbound()
+ */
+ public boolean isUpperbound() {
+ return false;
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+ public boolean isCompilationUnit()
+ {
+ return true;
+ }
+
+ private IClassFile getClassFile(char[] fileName) {
+ int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+ int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
+ if (pkgEnd == -1)
+ pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
+ if (jarSeparator != -1 && pkgEnd < jarSeparator) // if in a jar and no slash, it is a default package -> pkgEnd should be equal to jarSeparator
+ pkgEnd = jarSeparator;
+ if (pkgEnd == -1)
+ return null;
+ IPackageFragment pkg = getPackageFragment(fileName, pkgEnd, jarSeparator);
+ if (pkg == null) return null;
+ int start;
+ return pkg.getClassFile(new String(fileName, start = pkgEnd + 1, fileName.length - start));
+ }
+
+ public boolean isRecovered() {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnitResolver.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnitResolver.java
new file mode 100644
index 0000000..22ebd5e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/JavaScriptUnitResolver.java
@@ -0,0 +1,994 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.Compiler;
+import org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.wst.jsdt.internal.compiler.ICompilerRequestor;
+import org.eclipse.wst.jsdt.internal.compiler.IErrorHandlingPolicy;
+import org.eclipse.wst.jsdt.internal.compiler.IProblemFactory;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.env.IBinaryType;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.wst.jsdt.internal.compiler.util.Messages;
+import org.eclipse.wst.jsdt.internal.core.BinaryMember;
+import org.eclipse.wst.jsdt.internal.core.CancelableNameEnvironment;
+import org.eclipse.wst.jsdt.internal.core.CancelableProblemFactory;
+import org.eclipse.wst.jsdt.internal.core.JavaProject;
+import org.eclipse.wst.jsdt.internal.core.NameLookup;
+import org.eclipse.wst.jsdt.internal.core.SourceRefElement;
+import org.eclipse.wst.jsdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.wst.jsdt.internal.core.util.BindingKeyResolver;
+import org.eclipse.wst.jsdt.internal.core.util.CommentRecorderParser;
+import org.eclipse.wst.jsdt.internal.core.util.DOMFinder;
+import org.eclipse.wst.jsdt.internal.oaametadata.LibraryAPIs;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class JavaScriptUnitResolver extends Compiler {
+
+ /* A list of int */
+ static class IntArrayList {
+ public int[] list = new int[5];
+ public int length = 0;
+ public void add(int i) {
+ if (this.list.length == this.length) {
+ System.arraycopy(this.list, 0, this.list = new int[this.length*2], 0, this.length);
+ }
+ this.list[this.length++] = i;
+ }
+ }
+
+ /*
+ * The sources that were requested.
+ * Map from file name (char[]) to IJavaScriptUnit.
+ */
+ HashtableOfObject requestedSources;
+
+ /*
+ * The binding keys that were requested.
+ * Map from file name (char[]) to BindingKey (or ArrayList if multiple keys in the same file).
+ */
+ HashtableOfObject requestedKeys;
+
+ DefaultBindingResolver.BindingTables bindingTables;
+
+ boolean hasCompilationAborted;
+
+ private IProgressMonitor monitor;
+
+ /**
+ * Answer a new CompilationUnitVisitor using the given name environment and validator options.
+ * The environment and options will be in effect for the lifetime of the compiler.
+ * When the validator is run, compilation results are sent to the given requestor.
+ *
+ * @param environment org.eclipse.wst.jsdt.internal.compiler.api.env.INameEnvironment
+ * Environment used by the validator in order to resolve type and package
+ * names. The name environment implements the actual connection of the compiler
+ * to the outside world (for example, in batch mode the name environment is performing
+ * pure file accesses, reuse previous build state or connection to repositories).
+ * Note: the name environment is responsible for implementing the actual includepath
+ * rules.
+ *
+ * @param policy org.eclipse.wst.jsdt.internal.compiler.api.problem.IErrorHandlingPolicy
+ * Configurable part for problem handling, allowing the validator client to
+ * specify the rules for handling problems (stop on first error or accumulate
+ * them all) and at the same time perform some actions such as opening a dialog
+ * in UI when validating interactively.
+ * @see org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies
+ *
+ * @param compilerOptions The validator options to use for the resolution.
+ *
+ * @param requestor org.eclipse.wst.jsdt.internal.compiler.api.ICompilerRequestor
+ * Component which will receive and persist all compilation results and is intended
+ * to consume them as they are produced. Typically, in a batch compiler, it is
+ * responsible for writing out the actual .class files to the file system.
+ * @see org.eclipse.wst.jsdt.internal.compiler.CompilationResult
+ *
+ * @param problemFactory org.eclipse.wst.jsdt.internal.compiler.api.problem.IProblemFactory
+ * Factory used inside the validator to create problem descriptors. It allows the
+ * validator client to supply its own representation of compilation problems in
+ * order to avoid object conversions. Note that the factory is not supposed
+ * to accumulate the created problems, the validator will gather them all and hand
+ * them back as part of the javaScript unit result.
+ */
+ public JavaScriptUnitResolver(
+ INameEnvironment environment,
+ IErrorHandlingPolicy policy,
+ CompilerOptions compilerOptions,
+ ICompilerRequestor requestor,
+ IProblemFactory problemFactory,
+ IProgressMonitor monitor) {
+
+ super(environment, policy, compilerOptions, requestor, problemFactory);
+ this.hasCompilationAborted = false;
+ this.monitor =monitor;
+ }
+
+ /**
+ * Checks cancel state, runs parent operation, checks cancel state again.
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.Compiler#accept(org.eclipse.wst.jsdt.internal.compiler.env.IBinaryType, org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ this.checkCanceled();
+ super.accept(binaryType, packageBinding, accessRestriction);
+ this.checkCanceled();
+ }
+
+ /**
+ * Checks cancel state, runs parent operation, checks cancel state again.
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.Compiler#accept(org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
+ this.checkCanceled();
+ super.accept(sourceUnit, accessRestriction);
+ this.checkCanceled();
+ }
+
+ /**
+ * Checks cancel state, runs parent operation, checks cancel state again.
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.Compiler#accept(org.eclipse.wst.jsdt.internal.oaametadata.LibraryAPIs)
+ */
+ public void accept(LibraryAPIs libraryMetaData) {
+ this.checkCanceled();
+ super.accept(libraryMetaData);
+ this.checkCanceled();
+ }
+
+ /**
+ * Checks cancel state, adds additional source types, checks cancel state again.
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.Compiler#accept(org.eclipse.wst.jsdt.internal.compiler.env.ISourceType[], org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ this.checkCanceled();
+ // Need to reparse the entire source of the javaScript unit so as to get source positions
+ // (case of processing a source that was not known by beginToCompile (e.g. when asking to createBinding))
+ SourceTypeElementInfo sourceType = (SourceTypeElementInfo) sourceTypes[0];
+ accept((org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit) sourceType.getHandle().getJavaScriptUnit(), accessRestriction);
+
+ this.checkCanceled();
+ }
+
+ /**
+ * Add the initial set of javaScript units into the loop
+ * -> build javaScript unit declarations, their bindings and record their results.
+ */
+ protected void beginToCompile(org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit[] sourceUnits, String[] bindingKeys) {
+ int sourceLength = sourceUnits.length;
+ int keyLength = bindingKeys.length;
+ int maxUnits = sourceLength + keyLength;
+ this.totalUnits = 0;
+ this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+ int index = 0;
+
+ // walks the source units
+ this.requestedSources = new HashtableOfObject();
+ for (int i = 0; i < sourceLength; i++) {
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
+ CompilationUnitDeclaration parsedUnit;
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
+ try {
+ if (options.verbose) {
+ this.out.println(
+ Messages.bind(Messages.compilation_request,
+ new String[] {
+ String.valueOf(index++ + 1),
+ String.valueOf(maxUnits),
+ new String(sourceUnit.getFileName())
+ }));
+ }
+ // diet parsing for large collection of units
+ if (this.totalUnits < this.parseThreshold) {
+ parsedUnit = this.parser.parse(sourceUnit, unitResult);
+ } else {
+ parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
+ }
+ // initial type binding creation
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ addCompilationUnit(sourceUnit, parsedUnit);
+ this.requestedSources.put(unitResult.getFileName(), sourceUnit);
+ worked(1);
+ } finally {
+ sourceUnits[i] = null; // no longer hold onto the unit
+ }
+ }
+
+ // walk the binding keys
+ this.requestedKeys = new HashtableOfObject();
+ for (int i = 0; i < keyLength; i++) {
+ BindingKeyResolver resolver = new BindingKeyResolver(bindingKeys[i], this, this.lookupEnvironment);
+ resolver.parse(true/*pause after fully qualified name*/);
+ // If it doesn't have a type name, then it is either an array type, package or base type, which will definitely not have a javaScript unit.
+ // Skipping it will speed up performance because the call will open jars. (theodora)
+ CompilationUnitDeclaration parsedUnit = resolver.hasTypeName() ? resolver.getCompilationUnitDeclaration() : null;
+ if (parsedUnit != null) {
+ char[] fileName = parsedUnit.compilationResult.getFileName();
+ Object existing = this.requestedKeys.get(fileName);
+ if (existing == null)
+ this.requestedKeys.put(fileName, resolver);
+ else if (existing instanceof ArrayList)
+ ((ArrayList) existing).add(resolver);
+ else {
+ ArrayList list = new ArrayList();
+ list.add(existing);
+ list.add(resolver);
+ this.requestedKeys.put(fileName, list);
+ }
+
+ } else {
+ char[] key = resolver.hasTypeName()
+ ? resolver.getKey().toCharArray() // binary binding
+ : CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding
+ this.requestedKeys.put(key, resolver);
+ }
+ worked(1);
+ }
+
+ // binding resolution
+ lookupEnvironment.completeTypeBindings();
+ }
+
+ IBinding createBinding(String key) {
+ if (this.bindingTables == null)
+ throw new RuntimeException("Cannot be called outside ASTParser#createASTs(...)"); //$NON-NLS-1$
+ BindingKeyResolver keyResolver = new BindingKeyResolver(key, this, this.lookupEnvironment);
+ Binding compilerBinding = keyResolver.getCompilerBinding();
+ if (compilerBinding == null) return null;
+ DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null/*no owner*/, this.bindingTables, false);
+ return resolver.getBinding(compilerBinding);
+ }
+
+ public static JavaScriptUnit convert(CompilationUnitDeclaration compilationUnitDeclaration, char[] source, int apiLevel, Map options, boolean needToResolveBindings, WorkingCopyOwner owner, DefaultBindingResolver.BindingTables bindingTables, int flags, IProgressMonitor monitor) {
+ BindingResolver resolver = null;
+ AST ast = AST.newAST(apiLevel);
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ JavaScriptUnit compilationUnit = null;
+ ASTConverter converter = new ASTConverter(options, needToResolveBindings, monitor);
+ if (needToResolveBindings) {
+ resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, owner, bindingTables, (flags & IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ ast.setFlag(flags | AST.RESOLVED_BINDINGS);
+ } else {
+ resolver = new BindingResolver();
+ ast.setFlag(flags);
+ }
+ ast.setBindingResolver(resolver);
+ converter.setAST(ast);
+ compilationUnit = converter.convert(compilationUnitDeclaration, source);
+ compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+ return compilationUnit;
+ }
+
+ protected static CompilerOptions getCompilerOptions(Map options, boolean statementsRecovery) {
+ CompilerOptions compilerOptions = new CompilerOptions(options);
+ compilerOptions.performMethodsFullRecovery = statementsRecovery;
+ compilerOptions.performStatementsRecovery = statementsRecovery;
+ compilerOptions.parseLiteralExpressionsAsConstants = false;
+ compilerOptions.storeAnnotations = true /*store annotations in the bindings*/;
+ return compilerOptions;
+ }
+ /*
+ * Low-level API performing the actual compilation
+ */
+ protected static IErrorHandlingPolicy getHandlingPolicy() {
+
+ // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors() {
+ return false; // stop if there are some errors
+ }
+ };
+ }
+
+ /*
+ * Answer the component to which will be handed back compilation results from the compiler
+ */
+ protected static ICompilerRequestor getRequestor() {
+ return new ICompilerRequestor() {
+ public void acceptResult(CompilationResult compilationResult) {
+ // do nothing
+ }
+ };
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.Compiler#initializeParser()
+ */
+ public void initializeParser() {
+ this.parser = new CommentRecorderParser(this.problemReporter, false);
+ }
+ public void process(CompilationUnitDeclaration unit, int i) {
+ // don't resolve a second time the same unit (this would create the same binding twice)
+ char[] fileName = unit.compilationResult.getFileName();
+ if (!this.requestedKeys.containsKey(fileName) && !this.requestedSources.containsKey(fileName))
+ super.process(unit, i);
+ }
+ /*
+ * Compiler crash recovery in case of unexpected runtime exceptions
+ */
+ protected void handleInternalException(
+ Throwable internalException,
+ CompilationUnitDeclaration unit,
+ CompilationResult result) {
+ super.handleInternalException(internalException, unit, result);
+ if (unit != null) {
+ removeUnresolvedBindings(unit);
+ }
+ }
+
+ /*
+ * Compiler recovery in case of internal AbortCompilation event
+ */
+ protected void handleInternalException(
+ AbortCompilation abortException,
+ CompilationUnitDeclaration unit) {
+ super.handleInternalException(abortException, unit);
+ if (unit != null) {
+ removeUnresolvedBindings(unit);
+ }
+ this.hasCompilationAborted = true;
+ }
+
+ public static void parse(IJavaScriptUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
+ try {
+ CompilerOptions compilerOptions = new CompilerOptions(options);
+ Parser parser = new CommentRecorderParser(
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ compilerOptions,
+ new DefaultProblemFactory()),
+ false);
+ int length = compilationUnits.length;
+ if (monitor != null) monitor.beginTask("", length); //$NON-NLS-1$
+ for (int i = 0; i < length; i++) {
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit) compilationUnits[i];
+ CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+ parser.inferTypes(compilationUnitDeclaration, compilerOptions);
+
+ if (compilationUnitDeclaration.ignoreMethodBodies) {
+ compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+ // if initial diet parse did not work, no need to dig into method bodies.
+ continue;
+ }
+
+ //fill the methods bodies in order for the code to be generated
+ //real parse of the method....
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types != null) {
+ for (int j = types.length; --j >= 0;)
+ types[j].parseMethod(parser, compilationUnitDeclaration);
+ }
+
+ // convert AST
+ JavaScriptUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options, false/*don't resolve binding*/, null/*no owner needed*/, null/*no binding table needed*/, flags /* flags */, monitor);
+ node.setTypeRoot(compilationUnits[i]);
+
+ // accept AST
+ astRequestor.acceptAST(compilationUnits[i], node);
+
+ if (monitor != null) monitor.worked(1);
+ }
+ } finally {
+ if (monitor != null) monitor.done();
+ }
+ }
+
+ public static CompilationUnitDeclaration parse(
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ NodeSearcher nodeSearcher,
+ Map settings,
+ int flags) {
+ if (sourceUnit == null) {
+ throw new IllegalStateException();
+ }
+ CompilerOptions compilerOptions = new CompilerOptions(settings);
+ boolean statementsRecovery = (flags & IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
+ compilerOptions.performMethodsFullRecovery = statementsRecovery;
+ compilerOptions.performStatementsRecovery = statementsRecovery;
+ Parser parser = new CommentRecorderParser(
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ compilerOptions,
+ new DefaultProblemFactory()),
+ false);
+ CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+
+ parser.inferTypes(compilationUnitDeclaration, compilerOptions);
+ if (compilationUnitDeclaration.ignoreMethodBodies) {
+ compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+ // if initial diet parse did not work, no need to dig into method bodies.
+ return null;
+ }
+
+ if (nodeSearcher != null) {
+ char[] source = parser.scanner.getSource();
+ int searchPosition = nodeSearcher.position;
+ if (searchPosition < 0 || searchPosition > source.length) {
+ // the position is out of range. There is no need to search for a node.
+ return compilationUnitDeclaration;
+ }
+
+ compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);
+
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+ if (node == null) {
+ return compilationUnitDeclaration;
+ }
+
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+
+ if (node instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
+ } else if (enclosingTypeDeclaration != null) {
+ if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Initializer) {
+ ((org.eclipse.wst.jsdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
+ } else {
+ ((org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration)node).parseMethod(parser, compilationUnitDeclaration);
+ }
+ }
+ } else {
+ //fill the methods bodies in order for the code to be generated
+ //real parse of the method....
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types != null) {
+ for (int i = types.length; --i >= 0;)
+ types[i].parseMethod(parser, compilationUnitDeclaration);
+ }
+ }
+ return compilationUnitDeclaration;
+ }
+
+ public static void resolve(
+ IJavaScriptUnit[] compilationUnits,
+ String[] bindingKeys,
+ ASTRequestor requestor,
+ int apiLevel,
+ Map options,
+ IJavaScriptProject javaProject,
+ WorkingCopyOwner owner,
+ int flags,
+ IProgressMonitor monitor) {
+
+ CancelableNameEnvironment environment = null;
+ CancelableProblemFactory problemFactory = null;
+ try {
+ if (monitor != null) {
+ int amountOfWork = (compilationUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
+ monitor.beginTask("", amountOfWork); //$NON-NLS-1$
+ }
+ environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, monitor);
+ problemFactory = new CancelableProblemFactory(monitor);
+ JavaScriptUnitResolver resolver =
+ new JavaScriptUnitResolver(
+ environment,
+ getHandlingPolicy(),
+ getCompilerOptions(options, (flags & IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY) != 0),
+ getRequestor(),
+ problemFactory,
+ monitor);
+
+ resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, flags);
+ if (NameLookup.VERBOSE) {
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ } catch (JavaScriptModelException e) {
+ // project doesn't exist -> simple parse without resolving
+ parse(compilationUnits, requestor, apiLevel, options, flags, monitor);
+ } finally {
+ if (monitor != null) monitor.done();
+ if (environment != null) {
+ environment.monitor = null; // don't hold a reference to this external object
+ }
+ if (problemFactory != null) {
+ problemFactory.monitor = null; // don't hold a reference to this external object
+ }
+ }
+ }
+ public static CompilationUnitDeclaration resolve(
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ IJavaScriptProject javaProject,
+ NodeSearcher nodeSearcher,
+ Map options,
+ WorkingCopyOwner owner,
+ int flags,
+ IProgressMonitor monitor) throws JavaScriptModelException {
+
+ CompilationUnitDeclaration unit = null;
+ CancelableNameEnvironment environment = null;
+ CancelableProblemFactory problemFactory = null;
+ JavaScriptUnitResolver resolver = null;
+ try {
+ environment = new CancelableNameEnvironment(((JavaProject)javaProject), owner, monitor);
+ environment.setCompilationUnit(sourceUnit);
+ problemFactory = new CancelableProblemFactory(monitor);
+ resolver =
+ new JavaScriptUnitResolver(
+ environment,
+ getHandlingPolicy(),
+ getCompilerOptions(options, (flags & IJavaScriptUnit.ENABLE_STATEMENTS_RECOVERY) != 0),
+ getRequestor(),
+ problemFactory,
+ monitor);
+
+ unit =
+ resolver.resolve(
+ null, // no existing javaScript unit declaration
+ sourceUnit,
+ nodeSearcher,
+ true, // method verification
+ true, // analyze code
+ true); // generate code
+ if (resolver.hasCompilationAborted) {
+ // the bindings could not be resolved due to missing types in name environment
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
+ CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
+ final int problemCount = unit.compilationResult.problemCount;
+ if (problemCount != 0) {
+ unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
+ System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
+ unitDeclaration.compilationResult.problemCount = problemCount;
+ }
+ return unitDeclaration;
+ }
+ if (NameLookup.VERBOSE) {
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return unit;
+ } finally {
+ if (environment != null) {
+ environment.monitor = null; // don't hold a reference to this external object
+ }
+ if (problemFactory != null) {
+ problemFactory.monitor = null; // don't hold a reference to this external object
+ }
+ // first unit cleanup is done by caller, but cleanup all enqueued requested units (not processed)
+// if (resolver != null) {
+// for (int i = 1; i < resolver.totalUnits; i++) { // could be more requested units
+// CompilationUnitDeclaration parsedUnit = resolver.unitsToProcess[i];
+// if (parsedUnit.scope != null)
+// parsedUnit.scope.faultInTypes(); // force resolution of signatures, so clients can query DOM AST
+// parsedUnit.cleanUp();
+// }
+// }
+ }
+ }
+ public static IBinding[] resolve(
+ final IJavaScriptElement[] elements,
+ int apiLevel,
+ Map compilerOptions,
+ IJavaScriptProject javaProject,
+ WorkingCopyOwner owner,
+ int flags,
+ IProgressMonitor monitor) {
+
+ final int length = elements.length;
+ final HashMap sourceElementPositions = new HashMap(); // a map from IJavaScriptUnit to int[] (positions in elements)
+ int cuNumber = 0;
+ final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a map from String (binding key) to int (position in elements)
+ for (int i = 0; i < length; i++) {
+ IJavaScriptElement element = elements[i];
+ if (!(element instanceof SourceRefElement))
+ throw new IllegalStateException(element + " is not part of a javaScript unit or class file"); //$NON-NLS-1$
+ Object cu = element.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT);
+ if (cu != null) {
+ // source member
+ IntArrayList intList = (IntArrayList) sourceElementPositions.get(cu);
+ if (intList == null) {
+ sourceElementPositions.put(cu, intList = new IntArrayList());
+ cuNumber++;
+ }
+ intList.add(i);
+ } else {
+ // binary member
+ try {
+ String key = ((BinaryMember) element).getKey(true/*open to get resolved info*/);
+ binaryElementPositions.put(key, i);
+ } catch (JavaScriptModelException e) {
+ throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
+ }
+ }
+ }
+ IJavaScriptUnit[] cus = new IJavaScriptUnit[cuNumber];
+ sourceElementPositions.keySet().toArray(cus);
+
+ int bindingKeyNumber = binaryElementPositions.size();
+ String[] bindingKeys = new String[bindingKeyNumber];
+ binaryElementPositions.keysToArray(bindingKeys);
+
+ class Requestor extends ASTRequestor {
+ IBinding[] bindings = new IBinding[length];
+ public void acceptAST(IJavaScriptUnit source, JavaScriptUnit ast) {
+ // TODO (jerome) optimize to visit the AST only once
+ IntArrayList intList = (IntArrayList) sourceElementPositions.get(source);
+ for (int i = 0; i < intList.length; i++) {
+ final int index = intList.list[i];
+ SourceRefElement element = (SourceRefElement) elements[index];
+ DOMFinder finder = new DOMFinder(ast, element, true/*resolve binding*/);
+ try {
+ finder.search();
+ } catch (JavaScriptModelException e) {
+ throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
+ }
+ this.bindings[index] = finder.foundBinding;
+ }
+ }
+ public void acceptBinding(String bindingKey, IBinding binding) {
+ int index = binaryElementPositions.get(bindingKey);
+ this.bindings[index] = binding;
+ }
+ }
+ Requestor requestor = new Requestor();
+ resolve(cus, bindingKeys, requestor, apiLevel, compilerOptions, javaProject, owner, flags, monitor);
+ return requestor.bindings;
+ }
+ /*
+ * When unit result is about to be accepted, removed back pointers
+ * to unresolved bindings
+ */
+ public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
+ final org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+ if (types != null) {
+ for (int i = 0, max = types.length; i < max; i++) {
+ removeUnresolvedBindings(types[i]);
+ }
+ }
+ }
+ private void removeUnresolvedBindings(org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration type) {
+ final org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
+ if (memberTypes != null) {
+ for (int i = 0, max = memberTypes.length; i < max; i++){
+ removeUnresolvedBindings(memberTypes[i]);
+ }
+ }
+ if (type.binding != null && (type.binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+ type.binding = null;
+ }
+
+ final org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
+ if (fields != null) {
+ for (int i = 0, max = fields.length; i < max; i++){
+ if (fields[i].binding != null && (fields[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+ fields[i].binding = null;
+ }
+ }
+ }
+
+ final AbstractMethodDeclaration[] methods = type.methods;
+ if (methods != null) {
+ for (int i = 0, max = methods.length; i < max; i++){
+ if (methods[i].binding != null && (methods[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+ methods[i].binding = null;
+ }
+ }
+ }
+ }
+
+ private void resolve(IJavaScriptUnit[] compilationUnits, String[] bindingKeys, ASTRequestor astRequestor, int apiLevel, Map compilerOptions, WorkingCopyOwner owner, int flags) {
+
+ // temporararily connect ourselves to the ASTResolver - must disconnect when done
+ astRequestor.compilationUnitResolver = this;
+ this.bindingTables = new DefaultBindingResolver.BindingTables();
+ CompilationUnitDeclaration unit = null;
+ int i = 0;
+ try {
+ int length = compilationUnits.length;
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit[length];
+ System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
+ beginToCompile(sourceUnits, bindingKeys);
+ // process all units (some more could be injected in the loop by the lookup environment)
+ for (; i < this.totalUnits; i++) {
+ if (this.requestedSources.size() == 0 && this.requestedKeys.size() == 0) {
+ // no need to keep resolving if no more ASTs and no more binding keys are needed
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
+ // cleanup remaining units
+ for (; i < this.totalUnits; i++) {
+ this.unitsToProcess[i].cleanUp();
+ this.unitsToProcess[i] = null;
+ }
+ break;
+ }
+ unit = this.unitsToProcess[i];
+ try {
+ super.process(unit, i); // this.process(...) is optimized to not process already known units
+
+ // requested AST
+ char[] fileName = unit.compilationResult.getFileName();
+ IJavaScriptUnit source = (IJavaScriptUnit) this.requestedSources.get(fileName);
+ if (source != null) {
+ // convert AST
+ CompilationResult compilationResult = unit.compilationResult;
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
+ char[] contents = sourceUnit.getContents();
+ AST ast = AST.newAST(apiLevel);
+ ast.setFlag(flags | AST.RESOLVED_BINDINGS);
+ ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+ ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
+ BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, (flags & IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ ast.setBindingResolver(resolver);
+ converter.setAST(ast);
+ JavaScriptUnit compilationUnit = converter.convert(unit, contents);
+ compilationUnit.setTypeRoot(source);
+ compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
+ ast.setDefaultNodeFlag(0);
+ ast.setOriginalModificationCount(ast.modificationCount());
+
+ // pass it to requestor
+ astRequestor.acceptAST(source, compilationUnit);
+
+ worked(1);
+ }
+
+ // requested binding
+ Object key = this.requestedKeys.get(fileName);
+ if (key instanceof BindingKeyResolver) {
+ reportBinding(key, astRequestor, owner, unit);
+ worked(1);
+ } else if (key instanceof ArrayList) {
+ Iterator iterator = ((ArrayList) key).iterator();
+ while (iterator.hasNext()) {
+ reportBinding(iterator.next(), astRequestor, owner, unit);
+ worked(1);
+ }
+ }
+
+ // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
+ this.requestedSources.removeKey(fileName);
+ this.requestedKeys.removeKey(fileName);
+ } finally {
+ // cleanup javaScript unit result
+ unit.cleanUp();
+ }
+ this.unitsToProcess[i] = null; // release reference to processed unit declaration
+ this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ }
+
+ // remaining binding keys
+ DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, owner, this.bindingTables, (flags & IJavaScriptUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ Object[] keys = this.requestedKeys.valueTable;
+ for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
+ BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
+ if (keyResolver == null) continue;
+ Binding compilerBinding = keyResolver.getCompilerBinding();
+ IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
+ // pass it to requestor
+ astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
+ worked(1);
+ }
+ } catch (OperationCanceledException e) {
+ throw e;
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+ // disconnect ourselves from ast requestor
+ astRequestor.compilationUnitResolver = null;
+ }
+ }
+
+ private void reportBinding(Object key, ASTRequestor astRequestor, WorkingCopyOwner owner, CompilationUnitDeclaration unit) {
+ BindingKeyResolver keyResolver = (BindingKeyResolver) key;
+ Binding compilerBinding = keyResolver.getCompilerBinding();
+ if (compilerBinding != null) {
+ DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, false);
+ IBinding binding = resolver.getBinding(compilerBinding);
+ if (binding != null)
+ astRequestor.acceptBinding(keyResolver.getKey(), binding);
+ }
+ }
+
+ private CompilationUnitDeclaration resolve(
+ CompilationUnitDeclaration unit,
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ NodeSearcher nodeSearcher,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ try {
+
+ if (unit == null) {
+ // build and record parsed units
+ this.parseThreshold = 0; // will request a full parse
+ beginToCompile(new org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
+ // process all units (some more could be injected in the loop by the lookup environment)
+ unit = this.unitsToProcess[0];
+ } else {
+ // initial type binding creation
+ this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
+
+ // binding resolution
+ this.lookupEnvironment.completeTypeBindings();
+ }
+
+ if (nodeSearcher == null) {
+ this.parser.getMethodBodies(unit); // no-op if method bodies have already been parsed
+ } else {
+ int searchPosition = nodeSearcher.position;
+ char[] source = sourceUnit.getContents();
+ int length = source.length;
+ if (searchPosition >= 0 && searchPosition <= length) {
+ unit.traverse(nodeSearcher, unit.scope);
+
+ org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+
+ this.parser.scanner.setSource(source, unit.compilationResult);
+
+ if (node != null) {
+ org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+ if (node instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration)node).parseStatements(this.parser, unit);
+ } else if (enclosingTypeDeclaration != null) {
+ if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.Initializer) {
+ ((org.eclipse.wst.jsdt.internal.compiler.ast.Initializer) node).parseStatements(this.parser, enclosingTypeDeclaration, unit);
+ } else if (node instanceof org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration) {
+ ((org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration)node).parseMethod(this.parser, unit);
+ }
+ }
+ }
+ }
+ }
+
+ if (unit.scope != null) {
+ // fault in fields & methods
+ unit.scope.faultInTypes();
+ if (unit.scope != null && verifyMethods) {
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+ // verify inherited methods
+ unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
+ }
+ // type checking
+ unit.resolve();
+
+ // flow analysis
+ if (analyzeCode) unit.analyseCode();
+
+ }
+ if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration
+ this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ return unit;
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ return unit == null ? this.unitsToProcess[0] : unit;
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch(OperationCanceledException e) {
+ this.reset();
+ throw e;
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+ // No reset is performed there anymore since,
+ // within the CodeAssist (or related tools),
+ // the validator may be called *after* a call
+ // to this resolve(...) method. And such a call
+ // needs to have a validator with a non-empty
+ // environment.
+ // this.reset();
+ }
+ }
+ /*
+ * Internal API used to resolve a given javaScript unit. Can run a subset of the compilation process
+ */
+ public CompilationUnitDeclaration resolve(
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ return resolve(
+ null, /* no existing javaScript unit declaration*/
+ sourceUnit,
+ null/*no node searcher*/,
+ verifyMethods,
+ analyzeCode,
+ generateCode);
+ }
+
+ /*
+ * Internal API used to resolve a given javaScript unit. Can run a subset of the compilation process
+ */
+ public CompilationUnitDeclaration resolve(
+ CompilationUnitDeclaration unit,
+ org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit sourceUnit,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ return resolve(
+ unit,
+ sourceUnit,
+ null/*no node searcher*/,
+ verifyMethods,
+ analyzeCode,
+ generateCode);
+ }
+
+ /**
+ * Reports the amount of work completed on this resolvers {@link IProgressMonitor}
+ * if it has one. The canceled state of monitor will also be checked.
+ *
+ * @param work amount of work completed
+ *
+ * @see #checkCanceled()
+ */
+ private void worked(int work) {
+ if (this.monitor != null) {
+ this.checkCanceled();
+ this.monitor.worked(work);
+ }
+ }
+
+ /**
+ * Checks if the {@link IProgressMonitor} for this resolver is canceled,
+ * if it is then an {@link OperationCanceledException} is thrown.
+ *
+ * @throws OperationCanceledException - if this recievers monitor has been canceled
+ */
+ private void checkCanceled() {
+ if(this.monitor != null && this.monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/LabeledStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/LabeledStatement.java
new file mode 100644
index 0000000..bf8df0f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/LabeledStatement.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Labeled statement AST node type.
+ *
+ *
+ * LabeledStatement:
+ * Identifier : Statement
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class LabeledStatement extends Statement {
+
+ /**
+ * The "label" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor LABEL_PROPERTY =
+ new ChildPropertyDescriptor(LabeledStatement.class, "label", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(LabeledStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(LabeledStatement.class, propertyList);
+ addProperty(LABEL_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The label; lazily initialized; defaults to a unspecified,
+ * legal JavaScript identifier.
+ */
+ private SimpleName labelName = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an unspecified, but
+ * legal, statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new AST node for a labeled statement owned by the given
+ * AST. By default, the statement has an unspecified (but legal) label
+ * and an unspecified (but legal) statement.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ LabeledStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == LABEL_PROPERTY) {
+ if (get) {
+ return getLabel();
+ } else {
+ setLabel((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return LABELED_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ LabeledStatement result = new LabeledStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setLabel(
+ (SimpleName) ASTNode.copySubtree(target, getLabel()));
+ result.setBody(
+ (Statement) ASTNode.copySubtree(target, getBody()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getLabel());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the label of this labeled statement.
+ *
+ * @return the variable name node
+ */
+ public SimpleName getLabel() {
+ if (this.labelName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.labelName == null) {
+ preLazyInit();
+ this.labelName= new SimpleName(this.ast);
+ postLazyInit(this.labelName, LABEL_PROPERTY);
+ }
+ }
+ }
+ return this.labelName;
+ }
+
+ /**
+ * Sets the label of this labeled statement.
+ *
+ * @param label the new label
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setLabel(SimpleName label) {
+ if (label == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.labelName;
+ preReplaceChild(oldChild, label, LABEL_PROPERTY);
+ this.labelName = label;
+ postReplaceChild(oldChild, label, LABEL_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this labeled statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body= new EmptyStatement(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this labeled statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the body of a labeled statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the body of a LabeledStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.labelName == null ? 0 : getLabel().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/LineComment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/LineComment.java
new file mode 100644
index 0000000..4517bf5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/LineComment.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * End-of-line comment AST node type.
+ *
+ * End-of-line comments begin with "//",
+ * must end with a line delimiter (as per JLS 3.7),
+ * and must not contain line breaks.
+ *
+ *
+ * Note that this node type is a comment placeholder, and is
+ * only useful for recording the source range where a comment
+ * was found in a source string. It is not useful for creating
+ * comments.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class LineComment extends Comment {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(1);
+ createPropertyList(LineComment.class, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new line comment node owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ LineComment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return LINE_COMMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ LineComment result = new LineComment(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ListExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ListExpression.java
new file mode 100644
index 0000000..fb66721
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ListExpression.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ListExpression extends Expression {
+
+ /**
+ * The "expressions" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor EXPRESSIONS_PROPERTY =
+ new ChildListPropertyDescriptor(ListExpression.class, "expressions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(ListExpression.class, properyList);
+ addProperty(EXPRESSIONS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The list of expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList expressions =
+ new ASTNode.NodeList(EXPRESSIONS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an array initializer owned by the
+ * given AST. By default, the list of expressions is empty.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ListExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == EXPRESSIONS_PROPERTY) {
+ return expressions();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return LIST_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ListExpression result = new ListExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.expressions().addAll(ASTNode.copySubtrees(target, expressions()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.expressions);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of expressions in this array initializer.
+ *
+ * @return the live list of expressions
+ * (element type: Expression
)
+ */
+ public List expressions() {
+ return this.expressions;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.expressions.listSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/MemberRef.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/MemberRef.java
new file mode 100644
index 0000000..c2a45c5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/MemberRef.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a member reference within a doc comment
+ * ({@link JSdoc}). The principal uses of these are in "@see" and "@link"
+ * tag elements, for references to field members (and occasionally to method
+ * and constructor members).
+ *
+ * MemberRef:
+ * [ Name ] # Identifier
+ *
+ *
+ * @see JSdoc
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class MemberRef extends ASTNode implements IDocElement {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(MemberRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(MemberRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(MemberRef.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; null
for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The member name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript method name.
+ */
+ private SimpleName memberName = null;
+
+ /**
+ * Creates a new AST node for a member reference owned by the given
+ * AST. By default, the method reference is for a member with an
+ * unspecified, but legal, name; and no qualifier.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ MemberRef(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return MEMBER_REF;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ MemberRef result = new MemberRef(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this member reference, or
+ * null
if there is none.
+ *
+ * @return the qualifier name node, or null
if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this member reference.
+ *
+ * @param name the qualifier name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the referenced member.
+ *
+ * @return the member name node
+ */
+ public SimpleName getName() {
+ if (this.memberName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.memberName == null) {
+ preLazyInit();
+ this.memberName = new SimpleName(this.ast);
+ postLazyInit(this.memberName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.memberName;
+ }
+
+ /**
+ * Sets the name of the referenced member to the given name.
+ *
+ * @param name the new member name node
+ * @exception IllegalArgumentException if:
+ *
+ * - the name is
null
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.memberName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.memberName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the entity referred to by
+ * this member reference.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public final IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveReference(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.memberName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Message.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Message.java
new file mode 100644
index 0000000..2770b3d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Message.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Error message used to report potential errors found during the AST parsing
+ * or name resolution. Instances of this class are immutable.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class Message {
+
+ /**
+ * The message.
+ */
+ private String message;
+
+ /**
+ * The character index into the original source string, or -1 if none.
+ */
+ private int startPosition;
+
+ /**
+ * The length in characters of the original source file indicating
+ * where the source fragment corresponding to this message ends.
+ */
+ private int length;
+
+ /**
+ * Creates a message.
+ *
+ * @param message the localized message reported by the compiler
+ * @param startPosition the 0-based character index into the
+ * original source file, or -1
if no source position
+ * information is to be recorded for this message
+ * @throws IllegalArgumentException if the message is null
+ * @throws IllegalArgumentException if the startPosition is lower than -1.
+ */
+ public Message(String message, int startPosition) {
+ if (message == null) {
+ throw new IllegalArgumentException();
+ }
+ if (startPosition < -1) {
+ throw new IllegalArgumentException();
+ }
+ this.message = message;
+ this.startPosition = startPosition;
+ this.length = 0;
+ }
+
+ /**
+ * Creates a message.
+ *
+ * @param message the localized message reported by the compiler
+ * @param startPosition the 0-based character index into the
+ * original source file, or -1
if no source position
+ * information is to be recorded for this message
+ * @param length the length in character of the original source file indicating
+ * where the source fragment corresponding to this message ends. 0 or a negative number
+ * if none. A negative number will be converted to a 0-length.
+ * @throws IllegalArgumentException if the message is null
+ * @throws IllegalArgumentException if the startPosition is lower than -1.
+ */
+ public Message(String message, int startPosition, int length) {
+ if (message == null) {
+ throw new IllegalArgumentException();
+ }
+ if (startPosition < -1) {
+ throw new IllegalArgumentException();
+ }
+ this.message = message;
+ this.startPosition = startPosition;
+ if (length <= 0) {
+ this.length = 0;
+ } else {
+ this.length = length;
+ }
+ }
+
+ /**
+ * Returns the localized message.
+ *
+ * @return the localized message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Returns the character index into the original source file.
+ *
+ * @return the 0-based character index, or -1
+ * if no source position information is recorded for this
+ * message
+ * @deprecated Use {@link #getStartPosition()} instead.
+ * @see #getLength()
+ */
+ public int getSourcePosition() {
+ return getStartPosition();
+ }
+
+ /**
+ * Returns the character index into the original source file.
+ *
+ * @return the 0-based character index, or -1
+ * if no source position information is recorded for this
+ * message
+ * @see #getLength()
+ */
+ public int getStartPosition() {
+ return startPosition;
+ }
+
+ /**
+ * Returns the length in characters of the original source file indicating
+ * where the source fragment corresponding to this message ends.
+ *
+ * @return a length, or 0
+ * if no source length information is recorded for this message
+ * @see #getStartPosition()
+ */
+ public int getLength() {
+ return length;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Modifier.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Modifier.java
new file mode 100644
index 0000000..7ecb8d2
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Modifier.java
@@ -0,0 +1,706 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Modifier node.
+ *
+ * Modifier:
+ * public
+ * protected
+ * private
+ * static
+ * abstract
+ * final
+ * native
+ * synchronized
+ * transient
+ * volatile
+ * strictfp
+ *
+ *
+ * Note that JavaScript model class {@link org.eclipse.wst.jsdt.core.Flags} also
+ * provides the same constants as this class.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class Modifier extends ASTNode implements IExtendedModifier {
+
+ /**
+ * Modifier keywords (typesafe enumeration).
+ *
+ */
+ public static class ModifierKeyword {
+
+ /** "abstract" modifier with flag value {@link Modifier#ABSTRACT}. */
+ public static final ModifierKeyword ABSTRACT_KEYWORD = new ModifierKeyword("abstract", ABSTRACT);//$NON-NLS-1$
+
+ /** "final" modifier with flag value {@link Modifier#FINAL}. */
+ public static final ModifierKeyword FINAL_KEYWORD = new ModifierKeyword("final", FINAL);//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: String
;
+ * value type: Operator
).
+ */
+ private static final Map KEYWORDS;
+
+ /** "native" modifier with flag value {@link Modifier#NATIVE}. */
+ public static final ModifierKeyword NATIVE_KEYWORD = new ModifierKeyword("native", NATIVE);//$NON-NLS-1$
+
+ /** "private" modifier with flag value {@link Modifier#PRIVATE}. */
+ public static final ModifierKeyword PRIVATE_KEYWORD = new ModifierKeyword("private", PRIVATE);//$NON-NLS-1$
+
+ /** "protected" modifier with flag value {@link Modifier#PROTECTED}. */
+ public static final ModifierKeyword PROTECTED_KEYWORD = new ModifierKeyword("protected", PROTECTED);//$NON-NLS-1$
+
+ /** "public" modifier with flag value {@link Modifier#PUBLIC}. */
+ public static final ModifierKeyword PUBLIC_KEYWORD = new ModifierKeyword("public", PUBLIC);//$NON-NLS-1$
+
+ /** "static" modifier with flag value {@link Modifier#STATIC}. */
+ public static final ModifierKeyword STATIC_KEYWORD = new ModifierKeyword("static", STATIC);//$NON-NLS-1$
+
+ /** "strictfp" modifier with flag value {@link Modifier#STRICTFP}. */
+ public static final ModifierKeyword STRICTFP_KEYWORD = new ModifierKeyword("strictfp", STRICTFP);//$NON-NLS-1$
+
+ /** "synchronized" modifier with flag value {@link Modifier#SYNCHRONIZED}. */
+ public static final ModifierKeyword SYNCHRONIZED_KEYWORD = new ModifierKeyword("synchronized", SYNCHRONIZED);//$NON-NLS-1$
+
+ /** "transient" modifier with flag value {@link Modifier#TRANSIENT}. */
+ public static final ModifierKeyword TRANSIENT_KEYWORD = new ModifierKeyword("transient", TRANSIENT);//$NON-NLS-1$
+
+ /** "volatile" modifier with flag value {@link Modifier#VOLATILE}. */
+ public static final ModifierKeyword VOLATILE_KEYWORD = new ModifierKeyword("volatile", VOLATILE);//$NON-NLS-1$
+ static {
+ KEYWORDS = new HashMap(20);
+ ModifierKeyword[] ops = {
+ PUBLIC_KEYWORD,
+ PROTECTED_KEYWORD,
+ PRIVATE_KEYWORD,
+ STATIC_KEYWORD,
+ ABSTRACT_KEYWORD,
+ FINAL_KEYWORD,
+ NATIVE_KEYWORD,
+ SYNCHRONIZED_KEYWORD,
+ TRANSIENT_KEYWORD,
+ VOLATILE_KEYWORD,
+ STRICTFP_KEYWORD
+ };
+ for (int i = 0; i < ops.length; i++) {
+ KEYWORDS.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the modifier corresponding to the given single-bit flag value,
+ * or null
if none or if more than one bit is set.
+ *
+ * fromFlagValue
is the converse of toFlagValue
:
+ * that is, ModifierKind.fromFlagValue(k.toFlagValue()) == k
for
+ * all modifier keywords k
.
+ *
+ *
+ * @param flagValue the single-bit flag value for the modifier
+ * @return the modifier keyword, or null
if none
+ * @see #toFlagValue()
+ */
+ public static ModifierKeyword fromFlagValue(int flagValue) {
+ for (Iterator it = KEYWORDS.values().iterator(); it.hasNext(); ) {
+ ModifierKeyword k = (ModifierKeyword) it.next();
+ if (k.toFlagValue() == flagValue) {
+ return k;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the modifier corresponding to the given string,
+ * or null
if none.
+ *
+ * toKeyword
is the converse of toString
:
+ * that is, ModifierKind.toKeyword(k.toString()) == k
for
+ * all modifier keywords k
.
+ *
+ *
+ * @param keyword the lowercase string name for the modifier
+ * @return the modifier keyword, or null
if none
+ * @see #toString()
+ */
+ public static ModifierKeyword toKeyword(String keyword) {
+ return (ModifierKeyword) KEYWORDS.get(keyword);
+ }
+
+ /**
+ * The flag value for the modifier.
+ */
+ private int flagValue;
+
+ /**
+ * The keyword modifier string.
+ */
+ private String keyword;
+
+ /**
+ * Creates a new modifier with the given keyword.
+ *
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard modifiers.
+ *
+ *
+ * @param keyword the character sequence for the modifier
+ * @param flagValue flag value
+ */
+ private ModifierKeyword(String keyword, int flagValue) {
+ this.keyword = keyword;
+ this.flagValue = flagValue;
+ }
+
+ /**
+ * Returns the modifier flag value corresponding to this modifier keyword.
+ *
+ * @return one of the Modifier
constants
+ * @see #fromFlagValue(int)
+ */
+ public int toFlagValue() {
+ return this.flagValue;
+ }
+
+ /**
+ * Returns the keyword for the modifier.
+ *
+ * @return the keyword for the modifier
+ * @see #toKeyword(String)
+ */
+ public String toString() {
+ return this.keyword;
+ }
+ }
+
+ /**
+ * "abstract" modifier constant (bit mask).
+ * Applicable to types and methods.
+ *
+ */
+ public static final int ABSTRACT = 0x0400;
+
+ /**
+ * "final" modifier constant (bit mask).
+ * Applicable to types, methods, fields, and variables.
+ *
+ */
+ public static final int FINAL = 0x0010;
+
+ /**
+ * The "keyword" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor KEYWORD_PROPERTY =
+ new SimplePropertyDescriptor(Modifier.class, "keyword", Modifier.ModifierKeyword.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * "native" modifier constant (bit mask).
+ * Applicable only to methods.
+ *
+ */
+ public static final int NATIVE = 0x0100;
+
+ /**
+ * Modifier constant (bit mask, value 0) indicating no modifiers.
+ *
+ */
+ public static final int NONE = 0x0000;
+
+ /**
+ * "private" modifier constant (bit mask).
+ * Applicable to types, methods, constructors, and fields.
+ *
+ */
+ public static final int PRIVATE = 0x0002;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ /**
+ * "protected" modifier constant (bit mask).
+ * Applicable to types, methods, constructors, and fields.
+ *
+ */
+ public static final int PROTECTED = 0x0004;
+
+ /**
+ * "public" modifier constant (bit mask).
+ * Applicable to types, methods, constructors, and fields.
+ *
+ */
+ public static final int PUBLIC = 0x0001;
+
+ /**
+ * "static" modifier constant (bit mask).
+ * Applicable to types, methods, fields, and initializers.
+ *
+ */
+ public static final int STATIC = 0x0008;
+
+ /**
+ * "strictfp" modifier constant (bit mask).
+ * Applicable to types and methods.
+ *
+ */
+ public static final int STRICTFP = 0x0800;
+
+ /**
+ * "synchronized" modifier constant (bit mask).
+ * Applicable only to methods.
+ *
+ */
+ public static final int SYNCHRONIZED = 0x0020;
+
+ /**
+ * "transient" modifier constant (bit mask).
+ * Applicable only to fields.
+ *
+ */
+ public static final int TRANSIENT = 0x0080;
+
+ /**
+ * "volatile" modifier constant (bit mask).
+ * Applicable only to fields.
+ *
+ */
+ public static final int VOLATILE = 0x0040;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(Modifier.class, properyList);
+ addProperty(KEYWORD_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns whether the given flags includes the "abstract" modifier.
+ * Applicable to types and methods.
+ *
+ * @param flags the modifier flags
+ * @return true
if the ABSTRACT
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isAbstract(int flags) {
+ return (flags & ABSTRACT) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "final" modifier.
+ * Applicable to types, methods, fields, and variables.
+ *
+ * @param flags the modifier flags
+ * @return true
if the FINAL
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isFinal(int flags) {
+ return (flags & FINAL) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "native" modifier.
+ * Applicable only to methods.
+ *
+ * @param flags the modifier flags
+ * @return true
if the NATIVE
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isNative(int flags) {
+ return (flags & NATIVE) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "private" modifier.
+ * Applicable to types, methods, constructors, and fields.
+ *
+ * @param flags the modifier flags
+ * @return true
if the PRIVATE
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isPrivate(int flags) {
+ return (flags & PRIVATE) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "protected" modifier.
+ * Applicable to types, methods, constructors, and fields.
+ *
+ * @param flags the modifier flags
+ * @return true
if the PROTECTED
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isProtected(int flags) {
+ return (flags & PROTECTED) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "public" modifier.
+ * Applicable to types, methods, constructors, and fields.
+ *
+ * @param flags the modifier flags
+ * @return true
if the PUBLIC
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isPublic(int flags) {
+ return (flags & PUBLIC) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "static" modifier.
+ * Applicable to types, methods, fields, and initializers.
+ *
+ * @param flags the modifier flags
+ * @return true
if the STATIC
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isStatic(int flags) {
+ return (flags & STATIC) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "strictfp" modifier.
+ * Applicable to types and methods.
+ *
+ * @param flags the modifier flags
+ * @return true
if the STRICTFP
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isStrictfp(int flags) {
+ return (flags & STRICTFP) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "synchronized" modifier.
+ * Applicable only to methods.
+ *
+ * @param flags the modifier flags
+ * @return true
if the SYNCHRONIZED
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isSynchronized(int flags) {
+ return (flags & SYNCHRONIZED) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "transient" modifier.
+ * Applicable only to fields.
+ *
+ * @param flags the modifier flags
+ * @return true
if the TRANSIENT
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isTransient(int flags) {
+ return (flags & TRANSIENT) != 0;
+ }
+
+ /**
+ * Returns whether the given flags includes the "volatile" modifier.
+ * Applicable only to fields.
+ *
+ * @param flags the modifier flags
+ * @return true
if the VOLATILE
bit is
+ * set, and false
otherwise
+ *
+ */
+ public static boolean isVolatile(int flags) {
+ return (flags & VOLATILE) != 0;
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The modifier keyword; defaults to an unspecified modifier.
+ *
+ */
+ private ModifierKeyword modifierKeyword = ModifierKeyword.PUBLIC_KEYWORD;
+
+ /**
+ * Creates a new unparented modifier node owned by the given AST.
+ * By default, the node has unspecified (but legal) modifier.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ *
+ */
+ Modifier(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ ASTNode clone0(AST target) {
+ Modifier result = new Modifier(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setKeyword(getKeyword());
+ return result;
+ }
+
+ /**
+ * Returns the modifier keyword of this modifier node.
+ *
+ * @return the modifier keyword
+ *
+ */
+ public ModifierKeyword getKeyword() {
+ return this.modifierKeyword;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final int getNodeType0() {
+ return MODIFIER;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == KEYWORD_PROPERTY) {
+ if (get) {
+ return getKeyword();
+ } else {
+ setKeyword((ModifierKeyword) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /**
+ * Answer true if the receiver is the abstract modifier, false otherwise.
+ *
+ * @return true if the receiver is the abstract modifier, false otherwise
+ *
+ */
+ public boolean isAbstract() {
+ return this.modifierKeyword == ModifierKeyword.ABSTRACT_KEYWORD;
+ }
+
+ /**
+ * @see IExtendedModifier#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return false;
+ }
+
+ /**
+ * Answer true if the receiver is the final modifier, false otherwise.
+ *
+ * @return true if the receiver is the final modifier, false otherwise
+ *
+ */
+ public boolean isFinal() {
+ return this.modifierKeyword == ModifierKeyword.FINAL_KEYWORD;
+ }
+
+ /**
+ * @see IExtendedModifier#isModifier()
+ */
+ public boolean isModifier() {
+ return true;
+ }
+
+ /**
+ * Answer true if the receiver is the native modifier, false otherwise.
+ *
+ * @return true if the receiver is the native modifier, false otherwise
+ *
+ */
+ public boolean isNative() {
+ return this.modifierKeyword == ModifierKeyword.NATIVE_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the private modifier, false otherwise.
+ *
+ * @return true if the receiver is the private modifier, false otherwise
+ *
+ */
+ public boolean isPrivate() {
+ return this.modifierKeyword == ModifierKeyword.PRIVATE_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the protected modifier, false otherwise.
+ *
+ * @return true if the receiver is the protected modifier, false otherwise
+ *
+ */
+ public boolean isProtected() {
+ return this.modifierKeyword == ModifierKeyword.PROTECTED_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the public modifier, false otherwise.
+ *
+ * @return true if the receiver is the public modifier, false otherwise
+ *
+ */
+ public boolean isPublic() {
+ return this.modifierKeyword == ModifierKeyword.PUBLIC_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the static modifier, false otherwise.
+ *
+ * @return true if the receiver is the static modifier, false otherwise
+ *
+ */
+ public boolean isStatic() {
+ return this.modifierKeyword == ModifierKeyword.STATIC_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the strictfp modifier, false otherwise.
+ *
+ * @return true if the receiver is the strictfp modifier, false otherwise
+ *
+ */
+ public boolean isStrictfp() {
+ return this.modifierKeyword == ModifierKeyword.STRICTFP_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the synchronized modifier, false otherwise.
+ *
+ * @return true if the receiver is the synchronized modifier, false otherwise
+ *
+ */
+ public boolean isSynchronized() {
+ return this.modifierKeyword == ModifierKeyword.SYNCHRONIZED_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the transient modifier, false otherwise.
+ *
+ * @return true if the receiver is the transient modifier, false otherwise
+ *
+ */
+ public boolean isTransient() {
+ return this.modifierKeyword == ModifierKeyword.TRANSIENT_KEYWORD;
+ }
+
+ /**
+ * Answer true if the receiver is the volatile modifier, false otherwise.
+ *
+ * @return true if the receiver is the volatile modifier, false otherwise
+ *
+ */
+ public boolean isVolatile() {
+ return this.modifierKeyword == ModifierKeyword.VOLATILE_KEYWORD;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ int memSize() {
+ // treat ModifierKeyword as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /**
+ * Sets the modifier keyword of this modifier node.
+ *
+ * @param modifierKeyord the modifier keyword
+ * @exception IllegalArgumentException if the argument is null
+ *
+ */
+ public void setKeyword(ModifierKeyword modifierKeyord) {
+ if (modifierKeyord == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(KEYWORD_PROPERTY);
+ this.modifierKeyword = modifierKeyord;
+ postValueChange(KEYWORD_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NaiveASTFlattener.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NaiveASTFlattener.java
new file mode 100644
index 0000000..b02512f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NaiveASTFlattener.java
@@ -0,0 +1,1392 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * bug 227489 - Etienne Pfister
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Internal AST visitor for serializing an AST in a quick and dirty fashion.
+ * For various reasons the resulting string is not necessarily legal
+ * JavaScript code; and even if it is legal JavaScript code, it is not necessarily the string
+ * that corresponds to the given AST. Although useless for most purposes, it's
+ * fine for generating debug print strings.
+ *
+ * Example usage:
+ *
+ *
+ * NaiveASTFlattener p = new NaiveASTFlattener();
+ * node.accept(p);
+ * String result = p.getResult();
+ *
+ *
+ * Call the reset
method to clear the previous result before reusing an
+ * existing instance.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class NaiveASTFlattener extends ASTVisitor {
+
+ /**
+ * The string buffer into which the serialized representation of the AST is
+ * written.
+ */
+ private StringBuffer buffer;
+
+ private int indent = 0;
+
+ /**
+ * Creates a new AST printer.
+ */
+ NaiveASTFlattener() {
+ this.buffer = new StringBuffer();
+ }
+
+ /**
+ * Returns the string accumulated in the visit.
+ *
+ * @return the serialized
+ */
+ public String getResult() {
+ return this.buffer.toString();
+ }
+
+ /**
+ * Resets this printer so that it can be used again.
+ */
+ public void reset() {
+ this.buffer.setLength(0);
+ }
+
+ void printIndent() {
+ for (int i = 0; i < this.indent; i++)
+ this.buffer.append(" "); //$NON-NLS-1$
+ }
+
+ /**
+ * Appends the text representation of the given modifier flags, followed by a single space.
+ * Used for 3.0 modifiers and annotations.
+ *
+ * @param ext the list of modifier and annotation nodes
+ * (element type: IExtendedModifiers
)
+ */
+ void printModifiers(List ext) {
+// for (Iterator it = ext.iterator(); it.hasNext(); ) {
+// ASTNode p = (ASTNode) it.next();
+// p.accept(this);
+// this.buffer.append(" ");//$NON-NLS-1$
+// }
+ }
+
+ /**
+ * Appends the text representation of the given modifier flags, followed by a single space.
+ * Used for JLS2 modifiers.
+ *
+ * @param modifiers the modifier flags
+ */
+ void printModifiers(int modifiers) {
+// if (Modifier.isPublic(modifiers)) {
+// this.buffer.append("public ");//$NON-NLS-1$
+// }
+// if (Modifier.isProtected(modifiers)) {
+// this.buffer.append("protected ");//$NON-NLS-1$
+// }
+// if (Modifier.isPrivate(modifiers)) {
+// this.buffer.append("private ");//$NON-NLS-1$
+// }
+// if (Modifier.isStatic(modifiers)) {
+// this.buffer.append("static ");//$NON-NLS-1$
+// }
+// if (Modifier.isAbstract(modifiers)) {
+// this.buffer.append("abstract ");//$NON-NLS-1$
+// }
+// if (Modifier.isFinal(modifiers)) {
+// this.buffer.append("final ");//$NON-NLS-1$
+// }
+// if (Modifier.isSynchronized(modifiers)) {
+// this.buffer.append("synchronized ");//$NON-NLS-1$
+// }
+// if (Modifier.isVolatile(modifiers)) {
+// this.buffer.append("volatile ");//$NON-NLS-1$
+// }
+// if (Modifier.isNative(modifiers)) {
+// this.buffer.append("native ");//$NON-NLS-1$
+// }
+// if (Modifier.isStrictfp(modifiers)) {
+// this.buffer.append("strictfp ");//$NON-NLS-1$
+// }
+// if (Modifier.isTransient(modifiers)) {
+// this.buffer.append("transient ");//$NON-NLS-1$
+// }
+ }
+
+ /*
+ * @see ASTVisitor#visit(AnonymousClassDeclaration)
+ */
+ public boolean visit(AnonymousClassDeclaration node) {
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration b = (BodyDeclaration) it.next();
+ b.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayAccess)
+ */
+ public boolean visit(ArrayAccess node) {
+ node.getArray().accept(this);
+ this.buffer.append("[");//$NON-NLS-1$
+ node.getIndex().accept(this);
+ this.buffer.append("]");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayCreation)
+ */
+ public boolean visit(ArrayCreation node) {
+ this.buffer.append("new ");//$NON-NLS-1$
+ ArrayType at = node.getType();
+ int dims = at.getDimensions();
+ Type elementType = at.getElementType();
+ elementType.accept(this);
+ for (Iterator it = node.dimensions().iterator(); it.hasNext(); ) {
+ this.buffer.append("[");//$NON-NLS-1$
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ this.buffer.append("]");//$NON-NLS-1$
+ dims--;
+ }
+ // add empty "[]" for each extra array dimension
+ for (int i= 0; i < dims; i++) {
+ this.buffer.append("[]");//$NON-NLS-1$
+ }
+ if (node.getInitializer() != null) {
+ node.getInitializer().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayInitializer)
+ */
+ public boolean visit(ArrayInitializer node) {
+ this.buffer.append("[");//$NON-NLS-1$
+ for (Iterator it = node.expressions().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("]");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ArrayType)
+ */
+ public boolean visit(ArrayType node) {
+ node.getComponentType().accept(this);
+ this.buffer.append("[]");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Assignment)
+ */
+ public boolean visit(Assignment node) {
+ node.getLeftHandSide().accept(this);
+ this.buffer.append(node.getOperator().toString());
+ node.getRightHandSide().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Block)
+ */
+ public boolean visit(Block node) {
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+ // fix for inner function handling, Etienne Pfister
+ ASTNode s = (ASTNode) it.next();
+ s.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BlockComment)
+ *
+ */
+ public boolean visit(BlockComment node) {
+ printIndent();
+ this.buffer.append("/* */");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BooleanLiteral)
+ */
+ public boolean visit(BooleanLiteral node) {
+ if (node.booleanValue() == true) {
+ this.buffer.append("true");//$NON-NLS-1$
+ } else {
+ this.buffer.append("false");//$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(BreakStatement)
+ */
+ public boolean visit(BreakStatement node) {
+ printIndent();
+ this.buffer.append("break");//$NON-NLS-1$
+ if (node.getLabel() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getLabel().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ public boolean visit(FunctionExpression node) {
+ node.getMethod().accept(this);
+ return false;
+ }
+
+
+ /*
+ * @see ASTVisitor#visit(CatchClause)
+ */
+ public boolean visit(CatchClause node) {
+ this.buffer.append("catch (");//$NON-NLS-1$
+ node.getException().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(CharacterLiteral)
+ */
+ public boolean visit(CharacterLiteral node) {
+ this.buffer.append(node.getEscapedValue());
+ return false;
+ }
+
+ public boolean visit(RegularExpressionLiteral node) {
+ this.buffer.append(node.getRegularExpression());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ClassInstanceCreation)
+ */
+ public boolean visit(ClassInstanceCreation node) {
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("new ");//$NON-NLS-1$
+// if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+// node.internalGetName().accept(this);
+// }
+// if (node.getAST().apiLevel() >= AST.JLS3) {
+// if (!node.typeArguments().isEmpty()) {
+// this.buffer.append("<");//$NON-NLS-1$
+// for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+// Type t = (Type) it.next();
+// t.accept(this);
+// if (it.hasNext()) {
+// this.buffer.append(",");//$NON-NLS-1$
+// }
+// }
+// this.buffer.append(">");//$NON-NLS-1$
+// }
+// node.getType().accept(this);
+// }
+ node.getMember().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ if (node.getAnonymousClassDeclaration() != null) {
+ node.getAnonymousClassDeclaration().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(JavaScriptUnit)
+ */
+ public boolean visit(JavaScriptUnit node) {
+ if (node.getPackage() != null) {
+ node.getPackage().accept(this);
+ }
+ for (Iterator it = node.imports().iterator(); it.hasNext(); ) {
+ ImportDeclaration d = (ImportDeclaration) it.next();
+ d.accept(this);
+ }
+ for (Iterator it = node.types().iterator(); it.hasNext(); ) {
+ AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next();
+ d.accept(this);
+ }
+ for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+ ProgramElement d = (ProgramElement) it.next();
+ d.accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ConditionalExpression)
+ */
+ public boolean visit(ConditionalExpression node) {
+ node.getExpression().accept(this);
+ this.buffer.append(" ? ");//$NON-NLS-1$
+ node.getThenExpression().accept(this);
+ this.buffer.append(" : ");//$NON-NLS-1$
+ node.getElseExpression().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ConstructorInvocation)
+ */
+ public boolean visit(ConstructorInvocation node) {
+ printIndent();
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("this(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(");\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ContinueStatement)
+ */
+ public boolean visit(ContinueStatement node) {
+ printIndent();
+ this.buffer.append("continue");//$NON-NLS-1$
+ if (node.getLabel() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getLabel().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(DoStatement)
+ */
+ public boolean visit(DoStatement node) {
+ printIndent();
+ this.buffer.append("do ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ this.buffer.append(" while (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(");\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EmptyStatement)
+ */
+ public boolean visit(EmptyStatement node) {
+ printIndent();
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(EnhancedForStatement)
+ *
+ */
+ public boolean visit(EnhancedForStatement node) {
+ printIndent();
+ this.buffer.append("for (");//$NON-NLS-1$
+ node.getParameter().accept(this);
+ this.buffer.append(" : ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+
+
+ /*
+ * @see ASTVisitor#visit(ExpressionStatement)
+ */
+ public boolean visit(ExpressionStatement node) {
+ printIndent();
+ node.getExpression().accept(this);
+ if (node.getParent().getNodeType()!=ASTNode.FOR_IN_STATEMENT)
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldAccess)
+ */
+ public boolean visit(FieldAccess node) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FieldDeclaration)
+ */
+ public boolean visit(FieldDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+ f.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ForStatement)
+ */
+ public boolean visit(ForStatement node) {
+ printIndent();
+ this.buffer.append("for (");//$NON-NLS-1$
+ for (Iterator it = node.initializers().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) buffer.append(", ");//$NON-NLS-1$
+ }
+ this.buffer.append("; ");//$NON-NLS-1$
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ }
+ this.buffer.append("; ");//$NON-NLS-1$
+ for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) buffer.append(", ");//$NON-NLS-1$
+ }
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ public boolean visit(ForInStatement node) {
+ printIndent();
+ this.buffer.append("for (");//$NON-NLS-1$
+ if (node.getIterationVariable() != null) {
+ node.getIterationVariable().accept(this);
+ }
+ this.buffer.append(" in ");//$NON-NLS-1$
+ if (node.getCollection() != null) {
+ node.getCollection().accept(this);
+ }
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(IfStatement)
+ */
+ public boolean visit(IfStatement node) {
+ printIndent();
+ this.buffer.append("if (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getThenStatement().accept(this);
+ if (node.getElseStatement() != null) {
+ this.buffer.append(" else ");//$NON-NLS-1$
+ node.getElseStatement().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ImportDeclaration)
+ */
+ public boolean visit(ImportDeclaration node) {
+ printIndent();
+ this.buffer.append("import ");//$NON-NLS-1$
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isStatic()) {
+ this.buffer.append("static ");//$NON-NLS-1$
+ }
+ }
+ node.getName().accept(this);
+ if (node.isOnDemand()) {
+ this.buffer.append(".*");//$NON-NLS-1$
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(InfixExpression)
+ */
+ public boolean visit(InfixExpression node) {
+ node.getLeftOperand().accept(this);
+ this.buffer.append(' '); // for cases like x= i - -1; or x= i++ + ++i;
+ this.buffer.append(node.getOperator().toString());
+ this.buffer.append(' ');
+ node.getRightOperand().accept(this);
+ final List extendedOperands = node.extendedOperands();
+ if (extendedOperands.size() != 0) {
+ this.buffer.append(' ');
+ for (Iterator it = extendedOperands.iterator(); it.hasNext(); ) {
+ this.buffer.append(node.getOperator().toString()).append(' ');
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(InstanceofExpression)
+ */
+ public boolean visit(InstanceofExpression node) {
+ node.getLeftOperand().accept(this);
+ this.buffer.append(" instanceof ");//$NON-NLS-1$
+ node.getRightOperand().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Initializer)
+ */
+ public boolean visit(Initializer node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Javadoc)
+ */
+ public boolean visit(JSdoc node) {
+ printIndent();
+ this.buffer.append("/** ");//$NON-NLS-1$
+ for (Iterator it = node.tags().iterator(); it.hasNext(); ) {
+ ASTNode e = (ASTNode) it.next();
+ e.accept(this);
+ }
+ this.buffer.append("\n */\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(LabeledStatement)
+ */
+ public boolean visit(LabeledStatement node) {
+ printIndent();
+ node.getLabel().accept(this);
+ this.buffer.append(": ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(LineComment)
+ *
+ */
+ public boolean visit(LineComment node) {
+ this.buffer.append("//\n");//$NON-NLS-1$
+ return false;
+ }
+
+ public boolean visit(ListExpression node) {
+ for (Iterator it = node.expressions().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(MemberRef)
+ *
+ */
+ public boolean visit(MemberRef node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ }
+ this.buffer.append("#");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+
+ /*
+ * @see ASTVisitor#visit(FunctionRef)
+ *
+ */
+ public boolean visit(FunctionRef node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ }
+ this.buffer.append("#");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
+ FunctionRefParameter e = (FunctionRefParameter) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FunctionRefParameter)
+ *
+ */
+ public boolean visit(FunctionRefParameter node) {
+ node.getType().accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isVarargs()) {
+ this.buffer.append("...");//$NON-NLS-1$
+ }
+ }
+ if (node.getName() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getName().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FunctionDeclaration)
+ */
+ public boolean visit(FunctionDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ printIndent();
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ this.buffer.append("function ");//$NON-NLS-1$
+// if (!node.isConstructor()) {
+// if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+// node.internalGetReturnType().accept(this);
+// } else {
+// if (node.getReturnType2() != null) {
+// node.getReturnType2().accept(this);
+// } else {
+// // methods really ought to have a return type
+// this.buffer.append("void");//$NON-NLS-1$
+// }
+// }
+// this.buffer.append(" ");//$NON-NLS-1$
+// }
+ SimpleName name = node.getName();
+ if (name!=null)
+ name.accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
+ SingleVariableDeclaration v = (SingleVariableDeclaration) it.next();
+ v.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ for (int i = 0; i < node.getExtraDimensions(); i++) {
+ this.buffer.append("[]"); //$NON-NLS-1$
+ }
+ if (!node.thrownExceptions().isEmpty()) {
+ this.buffer.append(" throws ");//$NON-NLS-1$
+ for (Iterator it = node.thrownExceptions().iterator(); it.hasNext(); ) {
+ Name n = (Name) it.next();
+ n.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ if (node.getBody() == null) {
+ this.buffer.append(";\n");//$NON-NLS-1$
+ } else {
+ node.getBody().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(FunctionInvocation)
+ */
+ public boolean visit(FunctionInvocation node) {
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ if (node.getName()!=null)
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ if (node.getName()!=null)
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(Modifier)
+ *
+ */
+ public boolean visit(Modifier node) {
+ this.buffer.append(node.getKeyword().toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NullLiteral)
+ */
+ public boolean visit(NullLiteral node) {
+ this.buffer.append("null");//$NON-NLS-1$
+ return false;
+ }
+
+ public boolean visit(UndefinedLiteral node) {
+ this.buffer.append("undefined");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(NumberLiteral)
+ */
+ public boolean visit(NumberLiteral node) {
+ this.buffer.append(node.getToken());
+ return false;
+ }
+
+
+
+ /*
+ * @see ASTVisitor#visit(PrefixExpression)
+ */
+ public boolean visit(ObjectLiteral node) {
+ if (node.fields().isEmpty())
+ this.buffer.append("{}");//$NON-NLS-1$
+ else {
+ this.buffer.append("{\n");//$NON-NLS-1$
+ for (Iterator it = node.fields().iterator(); it.hasNext(); ) {
+ ObjectLiteralField field = (ObjectLiteralField) it.next();
+ field.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",\n");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("\n}");//$NON-NLS-1$
+ }
+ return false;
+ }
+
+ public boolean visit(ObjectLiteralField node) {
+ node.getFieldName().accept(this);
+ this.buffer.append(" : "); //$NON-NLS-1$
+ node.getInitializer().accept(this);
+ return false;
+ }
+
+
+ /*
+ * @see ASTVisitor#visit(PackageDeclaration)
+ */
+ public boolean visit(PackageDeclaration node) {
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ }
+ printIndent();
+ this.buffer.append("package ");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ParenthesizedExpression)
+ */
+ public boolean visit(ParenthesizedExpression node) {
+ this.buffer.append("(");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PostfixExpression)
+ */
+ public boolean visit(PostfixExpression node) {
+ node.getOperand().accept(this);
+ this.buffer.append(node.getOperator().toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PrefixExpression)
+ */
+ public boolean visit(PrefixExpression node) {
+ this.buffer.append(node.getOperator().toString());
+ node.getOperand().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(PrimitiveType)
+ */
+ public boolean visit(PrimitiveType node) {
+ this.buffer.append(node.getPrimitiveTypeCode().toString());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(QualifiedName)
+ */
+ public boolean visit(QualifiedName node) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(QualifiedType)
+ *
+ */
+ public boolean visit(QualifiedType node) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ReturnStatement)
+ */
+ public boolean visit(ReturnStatement node) {
+ printIndent();
+ this.buffer.append("return");//$NON-NLS-1$
+ if (node.getExpression() != null) {
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SimpleName)
+ */
+ public boolean visit(SimpleName node) {
+ this.buffer.append(node.getIdentifier());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SimpleType)
+ */
+ public boolean visit(SimpleType node) {
+ return true;
+ }
+
+
+ /*
+ * @see ASTVisitor#visit(SingleVariableDeclaration)
+ */
+ public boolean visit(SingleVariableDeclaration node) {
+ printIndent();
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.isVarargs()) {
+ this.buffer.append("...");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(" ");//$NON-NLS-1$
+ node.getName().accept(this);
+ for (int i = 0; i < node.getExtraDimensions(); i++) {
+ this.buffer.append("[]"); //$NON-NLS-1$
+ }
+ if (node.getInitializer() != null) {
+ this.buffer.append("=");//$NON-NLS-1$
+ node.getInitializer().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(StringLiteral)
+ */
+ public boolean visit(StringLiteral node) {
+ this.buffer.append(node.getEscapedValue());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperConstructorInvocation)
+ */
+ public boolean visit(SuperConstructorInvocation node) {
+ printIndent();
+ if (node.getExpression() != null) {
+ node.getExpression().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("super(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(");\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperFieldAccess)
+ */
+ public boolean visit(SuperFieldAccess node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("super.");//$NON-NLS-1$
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SuperMethodInvocation)
+ */
+ public boolean visit(SuperMethodInvocation node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("super.");//$NON-NLS-1$
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (!node.typeArguments().isEmpty()) {
+ this.buffer.append("<");//$NON-NLS-1$
+ for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+ Type t = (Type) it.next();
+ t.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(">");//$NON-NLS-1$
+ }
+ }
+ node.getName().accept(this);
+ this.buffer.append("(");//$NON-NLS-1$
+ for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+ Expression e = (Expression) it.next();
+ e.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(",");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(")");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SwitchCase)
+ */
+ public boolean visit(SwitchCase node) {
+ if (node.isDefault()) {
+ this.buffer.append("default :\n");//$NON-NLS-1$
+ } else {
+ this.buffer.append("case ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(":\n");//$NON-NLS-1$
+ }
+ this.indent++; //decremented in visit(SwitchStatement)
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(SwitchStatement)
+ */
+ public boolean visit(SwitchStatement node) {
+ this.buffer.append("switch (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+ Statement s = (Statement) it.next();
+ s.accept(this);
+ this.indent--; // incremented in visit(SwitchCase)
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+
+ /*
+ * @see ASTVisitor#visit(TagElement)
+ *
+ */
+ public boolean visit(TagElement node) {
+ if (node.isNested()) {
+ // nested tags are always enclosed in braces
+ this.buffer.append("{");//$NON-NLS-1$
+ } else {
+ // top-level tags always begin on a new line
+ this.buffer.append("\n * ");//$NON-NLS-1$
+ }
+ boolean previousRequiresWhiteSpace = false;
+ if (node.getTagName() != null) {
+ this.buffer.append(node.getTagName());
+ previousRequiresWhiteSpace = true;
+ }
+ boolean previousRequiresNewLine = false;
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ ASTNode e = (ASTNode) it.next();
+ // assume text elements include necessary leading and trailing whitespace
+ // but Name, MemberRef, FunctionRef, and nested TagElement do not include white space
+ boolean currentIncludesWhiteSpace = (e instanceof TextElement);
+ if (previousRequiresNewLine && currentIncludesWhiteSpace) {
+ this.buffer.append("\n * ");//$NON-NLS-1$
+ }
+ previousRequiresNewLine = currentIncludesWhiteSpace;
+ // add space if required to separate
+ if (previousRequiresWhiteSpace && !currentIncludesWhiteSpace) {
+ this.buffer.append(" "); //$NON-NLS-1$
+ }
+ e.accept(this);
+ previousRequiresWhiteSpace = !currentIncludesWhiteSpace && !(e instanceof TagElement);
+ }
+ if (node.isNested()) {
+ this.buffer.append("}");//$NON-NLS-1$
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TextElement)
+ *
+ */
+ public boolean visit(TextElement node) {
+ this.buffer.append(node.getText());
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ThisExpression)
+ */
+ public boolean visit(ThisExpression node) {
+ if (node.getQualifier() != null) {
+ node.getQualifier().accept(this);
+ this.buffer.append(".");//$NON-NLS-1$
+ }
+ this.buffer.append("this");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(ThrowStatement)
+ */
+ public boolean visit(ThrowStatement node) {
+ printIndent();
+ this.buffer.append("throw ");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TryStatement)
+ */
+ public boolean visit(TryStatement node) {
+ printIndent();
+ this.buffer.append("try ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) {
+ CatchClause cc = (CatchClause) it.next();
+ cc.accept(this);
+ }
+ if (node.getFinally() != null) {
+ this.buffer.append(" finally ");//$NON-NLS-1$
+ node.getFinally().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeDeclaration)
+ */
+ public boolean visit(TypeDeclaration node) {
+ if (node.getJavadoc() != null) {
+ node.getJavadoc().accept(this);
+ }
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ this.buffer.append("class ");//$NON-NLS-1$
+ node.getName().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ if (node.internalGetSuperclass() != null) {
+ this.buffer.append("extends ");//$NON-NLS-1$
+ node.internalGetSuperclass().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ if (node.getSuperclassType() != null) {
+ this.buffer.append("extends ");//$NON-NLS-1$
+ node.getSuperclassType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append("{\n");//$NON-NLS-1$
+ this.indent++;
+ for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+ BodyDeclaration d = (BodyDeclaration) it.next();
+ d.accept(this);
+ }
+ this.indent--;
+ printIndent();
+ this.buffer.append("}\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeDeclarationStatement)
+ */
+ public boolean visit(TypeDeclarationStatement node) {
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ node.internalGetTypeDeclaration().accept(this);
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ node.getDeclaration().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(TypeLiteral)
+ */
+ public boolean visit(TypeLiteral node) {
+ node.getType().accept(this);
+ this.buffer.append(".class");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationExpression)
+ */
+ public boolean visit(VariableDeclarationExpression node) {
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+ node.getType().accept(this);
+ this.buffer.append(" ");//$NON-NLS-1$
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+ f.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationFragment)
+ */
+ public boolean visit(VariableDeclarationFragment node) {
+ node.getName().accept(this);
+ for (int i = 0; i < node.getExtraDimensions(); i++) {
+ this.buffer.append("[]");//$NON-NLS-1$
+ }
+ if (node.getInitializer() != null) {
+ this.buffer.append("=");//$NON-NLS-1$
+ node.getInitializer().accept(this);
+ }
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(VariableDeclarationStatement)
+ */
+ public boolean visit(VariableDeclarationStatement node) {
+ printIndent();
+ if (node.getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ printModifiers(node.getModifiers());
+ }
+ if (node.getAST().apiLevel() >= AST.JLS3) {
+ printModifiers(node.modifiers());
+ }
+// Type type = node.getType();
+// if (type!=null)
+// type.accept(this);
+ this.buffer.append("var ");//$NON-NLS-1$
+ for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+ VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+ f.accept(this);
+ if (it.hasNext()) {
+ this.buffer.append(", ");//$NON-NLS-1$
+ }
+ }
+ this.buffer.append(";\n");//$NON-NLS-1$
+ return false;
+ }
+
+ /*
+ * @see ASTVisitor#visit(WhileStatement)
+ */
+ public boolean visit(WhileStatement node) {
+ printIndent();
+ this.buffer.append("while (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+ public boolean visit(WithStatement node) {
+ printIndent();
+ this.buffer.append("with (");//$NON-NLS-1$
+ node.getExpression().accept(this);
+ this.buffer.append(") ");//$NON-NLS-1$
+ node.getBody().accept(this);
+ return false;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Name.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Name.java
new file mode 100644
index 0000000..895b6f8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Name.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Abstract base class for all AST nodes that represent names.
+ * There are exactly two kinds of name: simple ones
+ * (SimpleName
) and qualified ones (QualifiedName
).
+ *
+ *
+ * Name:
+ * SimpleName
+ * QualifiedName
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class Name extends Expression implements IDocElement {
+
+ /**
+ * Approximate base size of an expression node instance in bytes,
+ * including object header and instance fields.
+ */
+ static final int BASE_NAME_NODE_SIZE = BASE_NODE_SIZE + 1 * 4;
+
+ /**
+ * This index represents the position inside a qualified name.
+ */
+ int index;
+
+ /**
+ * Creates a new AST node for a name owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Name(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns whether this name is a simple name
+ * (SimpleName
).
+ *
+ * @return true
if this is a simple name, and
+ * false
otherwise
+ */
+ public final boolean isSimpleName() {
+ return (this instanceof SimpleName);
+ }
+
+ /**
+ * Returns whether this name is a qualified name
+ * (QualifiedName
).
+ *
+ * @return true
if this is a qualified name, and
+ * false
otherwise
+ */
+ public final boolean isQualifiedName() {
+ return (this instanceof QualifiedName);
+ }
+
+ /**
+ * Resolves and returns the binding for the entity referred to by this name.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public final IBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveName(this);
+ }
+
+ /**
+ * Returns the standard dot-separated representation of this name.
+ * If the name is a simple name, the result is the name's identifier.
+ * If the name is a qualified name, the result is the name of the qualifier
+ * (as computed by this method) followed by "." followed by the name's
+ * identifier.
+ *
+ * @return the fully qualified name
+ *
+ */
+ public final String getFullyQualifiedName() {
+ if (isSimpleName()) {
+ // avoid creating garbage for common case
+ return ((SimpleName) this).getIdentifier();
+ } else {
+ StringBuffer buffer = new StringBuffer(50);
+ appendName(buffer);
+ return new String(buffer);
+ }
+ }
+
+ /**
+ * Appends the standard representation of this name to the given string
+ * buffer.
+ *
+ * @param buffer the buffer
+ *
+ */
+ abstract void appendName(StringBuffer buffer);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NodeEventHandler.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NodeEventHandler.java
new file mode 100644
index 0000000..12a16db
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NodeEventHandler.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * A node event handler is an internal mechanism for receiving
+ * notification of changes to nodes in an AST.
+ *
+ * The default implementation serves as the default event handler
+ * that does nothing. Internal subclasses do all the real work.
+ *
+ *
+ * @see AST#getEventHandler()
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class NodeEventHandler {
+
+ /**
+ * Creates a node event handler.
+ */
+ NodeEventHandler() {
+ // default implementation: do nothing
+ }
+
+ /**
+ * Reports that the given node is about to lose a child.
+ * The first half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node about to be modified
+ * @param child the node about to be removed
+ * @param property the child or child list property descriptor
+ * @see #postRemoveChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ *
+ */
+ void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("DEL1 " + property);
+ }
+
+ /**
+ * Reports that the given node has just lose a child.
+ * The second half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param child the child that was removed; note that this node is unparented
+ * @param property the child or child list property descriptor
+ * @see #preRemoveChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ *
+ */
+ void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("DEL2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to have a child replaced.
+ * The first half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node about to be modified
+ * @param child the node about to be replaced
+ * @param newChild the replacement child; note that this node is unparented
+ * @param property the child or child list property descriptor
+ * @see #preReplaceChildEvent(ASTNode, ASTNode, ASTNode, StructuralPropertyDescriptor)
+ *
+ */
+ void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("REP1 " + property);
+ }
+
+ /**
+ * Reports that the given node has had its child replaced. The second half
+ * of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param child the node that was replaced; note that this node is unparented
+ * @param newChild the replacement child
+ * @param property the child or child list property descriptor
+ * @see #postReplaceChildEvent(ASTNode, ASTNode, ASTNode, StructuralPropertyDescriptor)
+ *
+ */
+ void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("REP2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to gain a child.
+ * The first half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that to be modified
+ * @param child the node that is to be added as a child; note that this
+ * node is unparented; in the case of a child list property, the exact
+ * location of insertion is not supplied (but is known on the
+ * corresponding postAddChildEvent
to
+ * follow)
+ * @param property the child or child list property descriptor
+ * @see #postAddChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ *
+ */
+ void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("ADD1 " + property);
+ }
+
+ /**
+ * Reports that the given node has just gained a child.
+ * The second half of an event pair. The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param child the node that was added as a child
+ * @param property the child or child list property descriptor
+ * @see #preAddChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+ *
+ */
+ void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+ // do nothing
+ // System.out.println("ADD2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to change the value of a
+ * non-child property. The first half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node to be modified
+ * @param property the property descriptor
+ * @see #postValueChangeEvent(ASTNode, SimplePropertyDescriptor)
+ *
+ */
+ void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // do nothing
+ // System.out.println("MOD1 " + property);
+ }
+
+ /**
+ * Reports that the given node has just changed the value of a
+ * non-child property. The second half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param property the property descriptor
+ * @see #preValueChangeEvent(ASTNode, SimplePropertyDescriptor)
+ *
+ */
+ void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+ // do nothing
+ // System.out.println("MOD2 " + property);
+ }
+
+ /**
+ * Reports that the given node is about to be cloned.
+ * The first half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node to be modified
+ * @see #postCloneNodeEvent(ASTNode, ASTNode)
+ *
+ */
+ void preCloneNodeEvent(ASTNode node) {
+ // do nothing
+ // System.out.println("CLONE1");
+ }
+
+ /**
+ * Reports that the given node has just been cloned.
+ * The second half of an event pair.
+ * The default implementation does nothing.
+ *
+ * @param node the node that was modified
+ * @param clone the clone of node
+ * @see #preCloneNodeEvent(ASTNode)
+ *
+ */
+ void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+ // do nothing
+ // System.out.println("CLONE2");
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NodeSearcher.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NodeSearcher.java
new file mode 100644
index 0000000..f6283bb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NodeSearcher.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class NodeSearcher extends ASTVisitor {
+ public org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode found;
+ public TypeDeclaration enclosingType;
+ public int position;
+
+ NodeSearcher(int position) {
+ this.position = position;
+ }
+
+ public boolean visit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+
+ if (constructorDeclaration.declarationSourceStart <= position
+ && position <= constructorDeclaration.declarationSourceEnd) {
+ found = constructorDeclaration;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(
+ FieldDeclaration fieldDeclaration,
+ MethodScope scope) {
+ if (fieldDeclaration.declarationSourceStart <= position
+ && position <= fieldDeclaration.declarationSourceEnd) {
+ found = fieldDeclaration;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ if (initializer.declarationSourceStart <= position
+ && position <= initializer.declarationSourceEnd) {
+ found = initializer;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(
+ TypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ if (memberTypeDeclaration.declarationSourceStart <= position
+ && position <= memberTypeDeclaration.declarationSourceEnd) {
+ enclosingType = memberTypeDeclaration;
+ return true;
+
+ }
+ return false;
+ }
+
+ public boolean visit(
+ MethodDeclaration methodDeclaration,
+ Scope scope) {
+
+ if (methodDeclaration.declarationSourceStart <= position
+ && position <= methodDeclaration.declarationSourceEnd) {
+ found = methodDeclaration;
+ return false;
+ }
+ return true;
+ }
+
+ public boolean visit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ if (typeDeclaration.declarationSourceStart <= position
+ && position <= typeDeclaration.declarationSourceEnd) {
+ enclosingType = typeDeclaration;
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NullLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NullLiteral.java
new file mode 100644
index 0000000..9ed1a34
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NullLiteral.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null literal node.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class NullLiteral extends Expression {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(1);
+ createPropertyList(NullLiteral.class, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented null literal node owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ NullLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return NULL_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ NullLiteral result = new NullLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NumberLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NumberLiteral.java
new file mode 100644
index 0000000..7c1c619
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/NumberLiteral.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Number literal nodes.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class NumberLiteral extends Expression {
+
+ /**
+ * The "token" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor TOKEN_PROPERTY =
+ new SimplePropertyDescriptor(NumberLiteral.class, "token", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(NumberLiteral.class, propertyList);
+ addProperty(TOKEN_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The token string; defaults to the integer literal "0".
+ */
+ private String tokenValue = "0";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented number literal node owned by the given AST.
+ * By default, the number literal is the token "0
".
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ NumberLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == TOKEN_PROPERTY) {
+ if (get) {
+ return getToken();
+ } else {
+ setToken((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return NUMBER_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ NumberLiteral result = new NumberLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setToken(getToken());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the token of this number literal node. The value is the sequence
+ * of characters that would appear in the source program.
+ *
+ * @return the numeric literal token
+ */
+ public String getToken() {
+ return this.tokenValue;
+ }
+
+ /**
+ * Sets the token of this number literal node. The value is the sequence
+ * of characters that would appear in the source program.
+ *
+ * @param token the numeric literal token
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setToken(String token) {
+ // update internalSetToken(String) if this is changed
+ if (token == null || token.length() == 0) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = token.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ scanner.tokenizeComments = false;
+ scanner.tokenizeWhiteSpace = false;
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameDoubleLiteral:
+ case TerminalTokens.TokenNameIntegerLiteral:
+ case TerminalTokens.TokenNameFloatingPointLiteral:
+ case TerminalTokens.TokenNameLongLiteral:
+ break;
+ case TerminalTokens.TokenNameMINUS :
+ tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameDoubleLiteral:
+ case TerminalTokens.TokenNameIntegerLiteral:
+ case TerminalTokens.TokenNameFloatingPointLiteral:
+ case TerminalTokens.TokenNameLongLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid number literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid number literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ } finally {
+ scanner.tokenizeComments = true;
+ scanner.tokenizeWhiteSpace = true;
+ }
+ preValueChange(TOKEN_PROPERTY);
+ this.tokenValue = token;
+ postValueChange(TOKEN_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setToken(String) that doesn't do any validation.
+ */
+ void internalSetToken(String token) {
+ preValueChange(TOKEN_PROPERTY);
+ this.tokenValue = token;
+ postValueChange(TOKEN_PROPERTY);
+ }
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(tokenValue);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ObjectLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ObjectLiteral.java
new file mode 100644
index 0000000..8902ee1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ObjectLiteral.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ObjectLiteral extends Expression {
+
+ public static final ChildListPropertyDescriptor FIELDS_PROPERTY =
+ new ChildListPropertyDescriptor(ObjectLiteral.class, "fields", ObjectLiteralField.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(ObjectLiteral.class, properyList);
+ addProperty(FIELDS_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ private ASTNode.NodeList fields =
+ new ASTNode.NodeList(FIELDS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a cast expression owned by the given
+ * AST. By default, the type and expression are unspecified (but legal).
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ObjectLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == FIELDS_PROPERTY) {
+ return fields();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return OBJECT_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ObjectLiteral result = new ObjectLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.fields().addAll(ASTNode.copySubtrees(target, fields()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChildren(visitor, this.fields);
+ }
+ visitor.endVisit(this);
+ }
+
+ public List fields() {
+ return this.fields;
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + this.fields.listSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ObjectLiteralField.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ObjectLiteralField.java
new file mode 100644
index 0000000..523abe2
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ObjectLiteralField.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ObjectLiteralField extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor FIELD_NAME_PROPERTY =
+ new ChildPropertyDescriptor(ObjectLiteralField.class, "fieldName", Expression.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(ObjectLiteralField.class, "initializer", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(3);
+ createPropertyList(ObjectLiteralField.class, properyList);
+ addProperty(FIELD_NAME_PROPERTY, properyList);
+ addProperty(INITIALIZER_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Expression fieldName = null;
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression initializer = null;
+
+ /**
+ * Creates a new AST node for a cast expression owned by the given
+ * AST. By default, the type and expression are unspecified (but legal).
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ObjectLiteralField(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((Expression) child);
+ return null;
+ }
+ }
+ if (property == FIELD_NAME_PROPERTY) {
+ if (get) {
+ return getFieldName();
+ } else {
+ setFieldName((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return OBJECT_LITERAL_FIELD;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ObjectLiteralField result = new ObjectLiteralField(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setFieldName( (Expression) getFieldName().clone(target));
+ result.setInitializer((Expression) getInitializer().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getFieldName());
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the type in this cast expression.
+ *
+ * @return the type
+ */
+ public Expression getFieldName() {
+ if (this.fieldName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.fieldName == null) {
+ preLazyInit();
+ this.fieldName = new SimpleName(this.ast);
+ postLazyInit(this.fieldName, FIELD_NAME_PROPERTY);
+ }
+ }
+ }
+ return this.fieldName;
+ }
+
+ /**
+ * Sets the type in this cast expression to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setFieldName(Expression name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.fieldName;
+ preReplaceChild(oldChild, name, FIELD_NAME_PROPERTY);
+ this.fieldName = name;
+ postReplaceChild(oldChild, name, FIELD_NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the expression of this cast expression.
+ *
+ * @return the expression node
+ */
+ public Expression getInitializer() {
+ if (this.initializer == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.initializer == null) {
+ preLazyInit();
+ this.initializer = new SimpleName(this.ast);
+ postLazyInit(this.initializer, INITIALIZER_PROPERTY);
+ }
+ }
+ }
+ return this.initializer;
+ }
+
+ /**
+ * Sets the expression of this cast expression.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setInitializer(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.initializer;
+ preReplaceChild(oldChild, expression, INITIALIZER_PROPERTY);
+ this.initializer = expression;
+ postReplaceChild(oldChild, expression, INITIALIZER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.fieldName == null ? 0 : getFieldName().treeSize())
+ + (this.initializer == null ? 0 : getInitializer().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PackageBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PackageBinding.java
new file mode 100644
index 0000000..204f89c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PackageBinding.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+import org.eclipse.wst.jsdt.internal.core.NameLookup;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+
+/**
+ * Internal implementation of package bindings.
+ */
+class PackageBinding implements IPackageBinding {
+
+ private static final String[] NO_NAME_COMPONENTS = CharOperation.NO_STRINGS;
+ private static final String UNNAMED = Util.EMPTY_STRING;
+ private static final char PACKAGE_NAME_SEPARATOR = '.';
+
+ private org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding binding;
+ private String name;
+// private BindingResolver resolver;
+ private String[] components;
+
+ PackageBinding(org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) {
+ this.binding = binding;
+// this.resolver = resolver;
+ }
+
+
+ /*
+ * @see IBinding#getName()
+ */
+ public String getName() {
+ if (name == null) {
+ computeNameAndComponents();
+ }
+ return name;
+ }
+
+ /*
+ * @see IPackageBinding#isUnnamed()
+ */
+ public boolean isUnnamed() {
+ return getName().equals(UNNAMED);
+ }
+
+ /*
+ * @see IPackageBinding#getNameComponents()
+ */
+ public String[] getNameComponents() {
+ if (components == null) {
+ computeNameAndComponents();
+ }
+ return components;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.PACKAGE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ return Modifier.NONE;
+ }
+
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ return false;
+ }
+
+ /**
+ * @see IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /*
+ * @see IBinding#getJavaElement()
+ */
+ public IJavaScriptElement getJavaElement() {
+ INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; // a package binding always has a LooupEnvironment set
+ if (!(nameEnvironment instanceof SearchableEnvironment)) return null;
+ NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
+ if (nameLookup == null) return null;
+ IJavaScriptElement[] pkgs = nameLookup.findPackageFragments(getName(), false/*exact match*/);
+ if (pkgs == null) return null;
+ return pkgs[0];
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ return new String(this.binding.computeUniqueKey());
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ *
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof PackageBinding)) {
+ return false;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding packageBinding2 = ((PackageBinding) other).binding;
+ return CharOperation.equals(this.binding.compoundName, packageBinding2.compoundName);
+ }
+
+ private void computeNameAndComponents() {
+ char[][] compoundName = this.binding.compoundName;
+ if (compoundName == CharOperation.NO_CHAR_CHAR || compoundName == null) {
+ name = UNNAMED;
+ components = NO_NAME_COMPONENTS;
+ } else {
+ int length = compoundName.length;
+ components = new String[length];
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < length - 1; i++) {
+ components[i] = new String(compoundName[i]);
+ buffer.append(compoundName[i]).append(PACKAGE_NAME_SEPARATOR);
+ }
+ components[length - 1] = new String(compoundName[length - 1]);
+ buffer.append(compoundName[length - 1]);
+ name = buffer.toString();
+ }
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PackageDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PackageDeclaration.java
new file mode 100644
index 0000000..bd67713
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PackageDeclaration.java
@@ -0,0 +1,352 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Package declaration AST node type.
+ * For JLS2:
+ *
+ * PackageDeclaration:
+ * package Name ;
+ *
+ * For JLS3, annotations and doc comment
+ * were added:
+ *
+ * PackageDeclaration:
+ * [ jsdoc ] { Annotation } package Name ;
+ *
+ * Note that the standard AST parser only recognizes a jsdoc comment
+ * immediately preceding the package declaration when it occurs in the
+ * special package-info.js
javaScript unit (JLS3 7.4.1.1).
+ * The jsdoc comment in that file contains the package description.
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class PackageDeclaration extends ASTNode {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ new ChildPropertyDescriptor(PackageDeclaration.class, "javadoc", JSdoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(PackageDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(PackageDeclaration.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(PackageDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The doc comment, or null
if none.
+ * Defaults to none.
+ *
+ */
+ JSdoc optionalDocComment = null;
+
+ /**
+ * The annotations (element type: Annotation
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ */
+ private ASTNode.NodeList annotations = null;
+
+ /**
+ * The package name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript package identifier.
+ */
+ private Name packageName = null;
+
+ /**
+ * Creates a new AST node for a package declaration owned by the
+ * given AST. The package declaration initially has an unspecified,
+ * but legal, JavaScript identifier; and an empty list of annotations.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ PackageDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((JSdoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PACKAGE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PackageDeclaration result = new PackageDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.setJavadoc((JSdoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.annotations().addAll(ASTNode.copySubtrees(target, annotations()));
+ }
+ result.setName((Name) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.annotations);
+ }
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of annotations of this
+ * package declaration (added in JLS3 API).
+ *
+ * @return the live list of annotations
+ * (element type: Annotation
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List annotations() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.annotations == null) {
+ unsupportedIn2();
+ }
+ return this.annotations;
+ }
+
+ /**
+ * Returns the doc comment node.
+ *
+ * @return the doc comment node, or null
if none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public JSdoc getJavadoc() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.annotations == null) {
+ unsupportedIn2();
+ }
+ return this.optionalDocComment;
+ }
+
+ /**
+ * Sets or clears the doc comment node.
+ *
+ * @param docComment the doc comment node, or null
if none
+ * @exception IllegalArgumentException if the doc comment string is invalid
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public void setJavadoc(JSdoc docComment) {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.annotations == null) {
+ unsupportedIn2();
+ }
+ ASTNode oldChild = this.optionalDocComment;
+ preReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
+ this.optionalDocComment = docComment;
+ postReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
+ }
+
+ /**
+ * Returns the package name of this package declaration.
+ *
+ * @return the package name node
+ */
+ public Name getName() {
+ if (this.packageName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.packageName == null) {
+ preLazyInit();
+ this.packageName = new SimpleName(this.ast);
+ postLazyInit(this.packageName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.packageName;
+ }
+
+ /**
+ * Sets the package name of this package declaration to the given name.
+ *
+ * @param name the new package name
+ * @exception IllegalArgumentException if`:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(Name name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.packageName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.packageName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Resolves and returns the binding for the package declared in this package
+ * declaration.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public IPackageBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolvePackage(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.annotations == null ? 0 : this.annotations.listSize())
+ + (this.packageName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ParenthesizedExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ParenthesizedExpression.java
new file mode 100644
index 0000000..3fd3f65
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ParenthesizedExpression.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parenthesized expression AST node type.
+ *
+ *
+ * ParenthesizedExpression:
+ * ( Expression )
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ParenthesizedExpression extends Expression {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ParenthesizedExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ParenthesizedExpression.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new unparented parenthesized expression node owned by the given
+ * AST. By default, the parenthesized expression has an unspecified, but
+ * legal, expression.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ParenthesizedExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PARENTHESIZED_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ParenthesizedExpression result = new ParenthesizedExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this parenthesized expression.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this parenthesized expression.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PostfixExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PostfixExpression.java
new file mode 100644
index 0000000..9af97a5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PostfixExpression.java
@@ -0,0 +1,332 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Postfix expression AST node type.
+ *
+ *
+ * PostfixExpression:
+ * Expression PostfixOperator
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class PostfixExpression extends Expression {
+
+ /**
+ * Postfix operators (typesafe enumeration).
+ *
+ * PostfixOperator:
+ * ++
INCREMENT
+ * --
DECREMENT
+ *
+ */
+ public static class Operator {
+
+ /**
+ * The token for the operator.
+ */
+ private String token;
+
+ /**
+ * Creates a new postfix operator with the given token.
+ *
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ *
+ *
+ * @param token the character sequence for the operator
+ */
+ private Operator(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return token;
+ }
+
+ /** Postfix increment "++" operator. */
+ public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
+ /** Postfix decrement "--" operator. */
+ public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: String
;
+ * value type: Operator
).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ INCREMENT,
+ DECREMENT,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the postfix operator corresponding to the given string,
+ * or null
if none.
+ *
+ * toOperator
is the converse of toString
:
+ * that is, Operator.toOperator(op.toString()) == op
for
+ * all operators op
.
+ *
+ *
+ * @param token the character sequence for the operator
+ * @return the postfix operator, or null
if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+ }
+
+ /**
+ * The "operator" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(PostfixExpression.class, "operator", PostfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "operand" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(PostfixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(PostfixExpression.class, propertyList);
+ addProperty(OPERAND_PROPERTY, propertyList);
+ addProperty(OPERATOR_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The operator; defaults to an unspecified postfix operator.
+ */
+ private PostfixExpression.Operator operator =
+ PostfixExpression.Operator.INCREMENT;
+
+ /**
+ * The operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression operand = null;
+
+ /**
+ * Creates a new AST node for an postfix expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator and
+ * operand.
+ *
+ * @param ast the AST that is to own this node
+ */
+ PostfixExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == OPERAND_PROPERTY) {
+ if (get) {
+ return getOperand();
+ } else {
+ setOperand((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return POSTFIX_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PostfixExpression result = new PostfixExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setOperator(getOperator());
+ result.setOperand((Expression) getOperand().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getOperand());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this postfix expression.
+ *
+ * @return the operator
+ */
+ public PostfixExpression.Operator getOperator() {
+ return this.operator;
+ }
+
+ /**
+ * Sets the operator of this postfix expression.
+ *
+ * @param operator the operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(PostfixExpression.Operator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.operator = operator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the operand of this postfix expression.
+ *
+ * @return the operand expression node
+ */
+ public Expression getOperand() {
+ if (this.operand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.operand == null) {
+ preLazyInit();
+ this.operand= new SimpleName(this.ast);
+ postLazyInit(this.operand, OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.operand;
+ }
+
+ /**
+ * Sets the operand of this postfix expression.
+ *
+ * @param expression the operand expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.operand;
+ preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ this.operand = expression;
+ postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.operand == null ? 0 : getOperand().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PrefixExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PrefixExpression.java
new file mode 100644
index 0000000..b039fe4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PrefixExpression.java
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Prefix expression AST node type.
+ *
+ *
+ * PrefixExpression:
+ * PrefixOperator Expression
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class PrefixExpression extends Expression {
+
+ /**
+ * Prefix operators (typesafe enumeration).
+ *
+ * PrefixOperator:
+ * ++
INCREMENT
+ * --
DECREMENT
+ * +
PLUS
+ * -
MINUS
+ * ~
COMPLEMENT
+ * !
NOT
+ *
+ */
+ public static class Operator {
+
+ /**
+ * The token for the operator.
+ */
+ private String token;
+
+ /**
+ * Creates a new prefix operator with the given token.
+ *
+ * Note: this constructor is private. The only instances
+ * ever created are the ones for the standard operators.
+ *
+ *
+ * @param token the character sequence for the operator
+ */
+ private Operator(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Returns the character sequence for the operator.
+ *
+ * @return the character sequence for the operator
+ */
+ public String toString() {
+ return token;
+ }
+
+ /** Prefix increment "++" operator. */
+ public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
+ /** Prefix decrement "--" operator. */
+ public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
+ /** Unary plus "+" operator. */
+ public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
+ /** Unary minus "-" operator. */
+ public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
+ /** Bitwise complement "~" operator. */
+ public static final Operator COMPLEMENT = new Operator("~");//$NON-NLS-1$
+ /** Logical complement "!" operator. */
+ public static final Operator NOT = new Operator("!");//$NON-NLS-1$
+
+ /**
+ * Map from token to operator (key type: String
;
+ * value type: Operator
).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Operator[] ops = {
+ INCREMENT,
+ DECREMENT,
+ PLUS,
+ MINUS,
+ COMPLEMENT,
+ NOT,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the prefix operator corresponding to the given string,
+ * or null
if none.
+ *
+ * toOperator
is the converse of toString
:
+ * that is, Operator.toOperator(op.toString()) == op
for
+ * all operators op
.
+ *
+ *
+ * @param token the character sequence for the operator
+ * @return the prefix operator, or null
if none
+ */
+ public static Operator toOperator(String token) {
+ return (Operator) CODES.get(token);
+ }
+ }
+
+ /**
+ * The "operator" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
+ new SimplePropertyDescriptor(PrefixExpression.class, "operator", PrefixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "operand" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor OPERAND_PROPERTY =
+ new ChildPropertyDescriptor(PrefixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(PrefixExpression.class, propertyList);
+ addProperty(OPERATOR_PROPERTY, propertyList);
+ addProperty(OPERAND_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The operator; defaults to an unspecified prefix operator.
+ */
+ private PrefixExpression.Operator operator =
+ PrefixExpression.Operator.PLUS;
+
+ /**
+ * The operand; lazily initialized; defaults to an unspecified,
+ * but legal, simple name.
+ */
+ private Expression operand = null;
+
+ /**
+ * Creates a new AST node for an prefix expression owned by the given
+ * AST. By default, the node has unspecified (but legal) operator and
+ * operand.
+ *
+ * @param ast the AST that is to own this node
+ */
+ PrefixExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == OPERATOR_PROPERTY) {
+ if (get) {
+ return getOperator();
+ } else {
+ setOperator((Operator) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == OPERAND_PROPERTY) {
+ if (get) {
+ return getOperand();
+ } else {
+ setOperand((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PREFIX_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PrefixExpression result = new PrefixExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setOperator(getOperator());
+ result.setOperand((Expression) getOperand().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getOperand());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the operator of this prefix expression.
+ *
+ * @return the operator
+ */
+ public PrefixExpression.Operator getOperator() {
+ return this.operator;
+ }
+
+ /**
+ * Sets the operator of this prefix expression.
+ *
+ * @param operator the operator
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setOperator(PrefixExpression.Operator operator) {
+ if (operator == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(OPERATOR_PROPERTY);
+ this.operator = operator;
+ postValueChange(OPERATOR_PROPERTY);
+ }
+
+ /**
+ * Returns the operand of this prefix expression.
+ *
+ * @return the operand expression node
+ */
+ public Expression getOperand() {
+ if (this.operand == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.operand == null) {
+ preLazyInit();
+ this.operand= new SimpleName(this.ast);
+ postLazyInit(this.operand, OPERAND_PROPERTY);
+ }
+ }
+ }
+ return this.operand;
+ }
+
+ /**
+ * Sets the operand of this prefix expression.
+ *
+ * @param expression the operand expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setOperand(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.operand;
+ preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ this.operand = expression;
+ postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.operand == null ? 0 : getOperand().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PrimitiveType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PrimitiveType.java
new file mode 100644
index 0000000..50c357b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/PrimitiveType.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Primitive type nodes.
+ *
+ * PrimitiveType:
+ * byte
+ * short
+ * char
+ * int
+ * long
+ * float
+ * double
+ * boolean
+ * void
+ *
+ *
+ * Note that due to the fact that AST nodes belong to a specific AST and
+ * have a specific parent, there needs to multiple instances of these
+ * nodes.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class PrimitiveType extends Type {
+
+ /**
+ * Primitive type codes (typesafe enumeration).
+ *
+ * byte BYTE
+ * short SHORT
+ * char CHAR
+ * int INT
+ * long LONG
+ * float FLOAT
+ * double DOUBLE
+ * boolean BOOLEAN
+ * void VOID
+ *
+ */
+ public static class Code {
+
+ /**
+ * The name of the type.
+ */
+ private String name;
+
+ /**
+ * Creates a new primitive type code with the given name.
+ *
+ * Note: this constructor is package-private. The only instances
+ * ever created are the ones for the standard primitive types.
+ *
+ *
+ * @param name the standard name of the primitive type
+ */
+ Code(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the standard name of the primitive type.
+ *
+ * @return the standard name of the primitive type
+ */
+ public String toString() {
+ return name;
+ }
+ }
+
+ /** Type code for the primitive type "int". */
+ public static final Code INT = new Code("int");//$NON-NLS-1$
+ /** Type code for the primitive type "char". */
+ public static final Code CHAR = new Code("char");//$NON-NLS-1$
+ /** Type code for the primitive type "boolean". */
+ public static final Code BOOLEAN = new Code("boolean");//$NON-NLS-1$
+ /** Type code for the primitive type "short". */
+ public static final Code SHORT = new Code("short");//$NON-NLS-1$
+ /** Type code for the primitive type "long". */
+ public static final Code LONG = new Code("long");//$NON-NLS-1$
+ /** Type code for the primitive type "float". */
+ public static final Code FLOAT = new Code("float");//$NON-NLS-1$
+ /** Type code for the primitive type "double". */
+ public static final Code DOUBLE = new Code("double");//$NON-NLS-1$
+ /** Type code for the primitive type "byte". */
+ public static final Code BYTE = new Code("byte");//$NON-NLS-1$
+ /** Type code for the primitive type "any". */
+ public static final Code ANY_CODE = new Code("any");//$NON-NLS-1$
+
+ /** Type code for the primitive type "void". Note that "void" is
+ * special in that its only legitimate uses are as a method return
+ * type and as a type literal.
+ */
+ public static final Code VOID = new Code("void");//$NON-NLS-1$
+
+ /**
+ * The primitive type code; one of the PrimitiveType constants; default
+ * is int.
+ */
+ private PrimitiveType.Code typeCode = INT;
+
+ /**
+ * Map from token to primitive type code (key type: String
;
+ * value type: PrimitiveType.Code
).
+ */
+ private static final Map CODES;
+ static {
+ CODES = new HashMap(20);
+ Code[] ops = {
+ INT,
+ BYTE,
+ CHAR,
+ BOOLEAN,
+ SHORT,
+ LONG,
+ FLOAT,
+ DOUBLE,
+ VOID,
+ ANY_CODE,
+ };
+ for (int i = 0; i < ops.length; i++) {
+ CODES.put(ops[i].toString(), ops[i]);
+ }
+ }
+
+ /**
+ * Returns the primitive type code corresponding to the given string,
+ * or null
if none.
+ *
+ * toCode
is the converse of toString
:
+ * that is,
+ * PrimitiveType.Code.toCode(code.toString()) == code
+ * for all type code code
.
+ *
+ *
+ * @param token the standard name of the primitive type
+ * @return the primitive type code, or null
if none
+ */
+ public static PrimitiveType.Code toCode(String token) {
+ return (PrimitiveType.Code) CODES.get(token);
+ }
+
+ /**
+ * The "primitiveTypeCode" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor PRIMITIVE_TYPE_CODE_PROPERTY =
+ new SimplePropertyDescriptor(PrimitiveType.class, "primitiveTypeCode", PrimitiveType.Code.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(PrimitiveType.class, propertyList);
+ addProperty(PRIMITIVE_TYPE_CODE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+
+ public static PrimitiveType createAnyType(AST ast)
+ {
+ PrimitiveType type = new PrimitiveType(ast);
+ type.setPrimitiveTypeCode(ANY_CODE);
+ return type;
+ }
+
+
+ /**
+ * Creates a new unparented node for a primitive type owned by the given
+ * AST. By default, the node has type "int".
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ PrimitiveType(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == PRIMITIVE_TYPE_CODE_PROPERTY) {
+ if (get) {
+ return getPrimitiveTypeCode();
+ } else {
+ setPrimitiveTypeCode((Code) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return PRIMITIVE_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ PrimitiveType result = new PrimitiveType(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setPrimitiveTypeCode(getPrimitiveTypeCode());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the primitive type code.
+ *
+ * @return one of the primitive type code constants declared in this
+ * class
+ */
+ public PrimitiveType.Code getPrimitiveTypeCode() {
+ return this.typeCode;
+ }
+
+ /**
+ * Sets the primitive type code.
+ *
+ * @param typeCode one of the primitive type code constants declared in
+ * this class
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setPrimitiveTypeCode(PrimitiveType.Code typeCode) {
+ if (typeCode == null) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(PRIMITIVE_TYPE_CODE_PROPERTY);
+ this.typeCode = typeCode;
+ postValueChange(PRIMITIVE_TYPE_CODE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ProgramElement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ProgramElement.java
new file mode 100644
index 0000000..299c771
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ProgramElement.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class ProgramElement extends ASTNode {
+
+ ProgramElement(AST ast) {
+ super(ast);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/QualifiedName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/QualifiedName.java
new file mode 100644
index 0000000..198bb3f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/QualifiedName.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * AST node for a qualified name. A qualified name is defined recursively
+ * as a simple name preceded by a name, which qualifies it. Expressing it this
+ * way means that the qualifier and the simple name get their own AST nodes.
+ *
+ * QualifiedName:
+ * Name . SimpleName
+ *
+ *
+ * See FieldAccess
for guidelines on handling other expressions
+ * that resemble qualified names.
+ *
+ *
+ * @see FieldAccess
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class QualifiedName extends Name {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedName.class, "qualifier", Name.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedName.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(QualifiedName.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The identifier; lazily initialized; defaults to a unspecified, legal
+ * JavaScript identifier.
+ */
+ private Name qualifier = null;
+
+ /**
+ * The name being qualified; lazily initialized; defaults to a unspecified,
+ * legal JavaScript identifier.
+ */
+ private SimpleName name = null;
+
+ /**
+ * Creates a new AST node for a qualified name owned by the given AST.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ QualifiedName(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return QUALIFIED_NAME;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ QualifiedName result = new QualifiedName(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setQualifier((Name) getQualifier().clone(target));
+ result.setName((SimpleName) getName().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier part of this qualified name.
+ *
+ * @return the qualifier part of this qualified name
+ */
+ public Name getQualifier() {
+ if (this.qualifier == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.qualifier == null) {
+ preLazyInit();
+ this.qualifier = new SimpleName(this.ast);
+ postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+ }
+ }
+ }
+ return this.qualifier;
+ }
+
+ /**
+ * Sets the qualifier of this qualified name to the given name.
+ *
+ * @param qualifier the qualifier of this qualified name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setQualifier(Name qualifier) {
+ if (qualifier == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.qualifier;
+ preReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
+ this.qualifier = qualifier;
+ postReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name part of this qualified name.
+ *
+ * @return the name being qualified
+ */
+ public SimpleName getName() {
+ if (this.name == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.name == null) {
+ preLazyInit();
+ this.name = new SimpleName(this.ast);
+ postLazyInit(this.name, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.name;
+ }
+
+ /**
+ * Sets the name part of this qualified name to the given simple name.
+ *
+ * @param name the identifier of this qualified name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.name;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.name = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on Name.
+ */
+ void appendName(StringBuffer buffer) {
+ getQualifier().appendName(buffer);
+ buffer.append('.');
+ getName().appendName(buffer);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NAME_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.name == null ? 0 : getName().treeSize())
+ + (this.qualifier == null ? 0 : getQualifier().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/QualifiedType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/QualifiedType.java
new file mode 100644
index 0000000..65b558f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/QualifiedType.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a qualified type (added in JLS3 API).
+ *
+ * QualifiedType:
+ * Type . SimpleName
+ *
+ *
+ * Not all node arragements will represent legal JavaScript constructs. In particular,
+ * it is nonsense if the type is an array type or primitive type. The normal use
+ * is when the type is a simple or parameterized type.
+ *
+ *
+ * A type like "A.B" can be represented either of two ways:
+ *
+ * -
+ *
QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))
+ *
+ * -
+ *
SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))
+ *
+ *
+ * The first form is preferred when "A" is known to be a type. However, a
+ * parser cannot always determine this. Clients should be prepared to handle
+ * either rather than make assumptions. (Note also that the first form
+ * became possible as of JLS3; only the second form existed in JLS2 API.)
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class QualifiedType extends Type {
+ /**
+ * This index represents the position inside a parameterized qualified type.
+ */
+ int index;
+
+ /**
+ * The "qualifier" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedType.class, "qualifier", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(QualifiedType.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(QualifiedType.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type node; lazily initialized; defaults to a type with
+ * an unspecfied, but legal, simple name.
+ */
+ private Type qualifier = null;
+
+ /**
+ * The name being qualified; lazily initialized; defaults to a unspecified,
+ * legal JavaScript identifier.
+ */
+ private SimpleName name = null;
+
+ /**
+ * Creates a new unparented node for a qualified type owned by the
+ * given AST. By default, an unspecified, but legal, qualifier and name.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ QualifiedType(AST ast) {
+ super(ast);
+ unsupportedIn2();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Type) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return QUALIFIED_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ QualifiedType result = new QualifiedType(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setQualifier((Type) ((ASTNode) getQualifier()).clone(target));
+ result.setName((SimpleName) ((ASTNode) getName()).clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this qualified type.
+ *
+ * @return the qualifier of this qualified type
+ */
+ public Type getQualifier() {
+ if (this.qualifier == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.qualifier == null) {
+ preLazyInit();
+ this.qualifier = new SimpleType(this.ast);
+ postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+ }
+ }
+ }
+ return this.qualifier;
+ }
+
+ /**
+ * Sets the qualifier of this qualified type to the given type.
+ *
+ * @param type the new qualifier of this qualified type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setQualifier(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.qualifier;
+ preReplaceChild(oldChild, type, QUALIFIER_PROPERTY);
+ this.qualifier = type;
+ postReplaceChild(oldChild, type, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name part of this qualified type.
+ *
+ * @return the name being qualified
+ */
+ public SimpleName getName() {
+ if (this.name == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.name == null) {
+ preLazyInit();
+ this.name = new SimpleName(this.ast);
+ postLazyInit(this.name, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.name;
+ }
+
+ /**
+ * Sets the name part of this qualified type to the given simple name.
+ *
+ * @param name the identifier of this qualified name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.name;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.name = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.qualifier == null ? 0 : getQualifier().treeSize())
+ + (this.name == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RecoveredTypeBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RecoveredTypeBinding.java
new file mode 100644
index 0000000..36134a9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RecoveredTypeBinding.java
@@ -0,0 +1,580 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+import org.eclipse.wst.jsdt.internal.core.CompilationUnit;
+
+/**
+ * This class represents the recovered binding for a type
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class RecoveredTypeBinding implements ITypeBinding {
+
+ private VariableDeclaration variableDeclaration;
+ private Type currentType;
+ private BindingResolver resolver;
+ private int dimensions;
+ private RecoveredTypeBinding innerTypeBinding;
+ private ITypeBinding[] typeArguments;
+ private org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding referenceBinding;
+
+ RecoveredTypeBinding(BindingResolver resolver, VariableDeclaration variableDeclaration) {
+ this.variableDeclaration = variableDeclaration;
+ this.resolver = resolver;
+ this.currentType = getType();
+ this.dimensions = variableDeclaration.getExtraDimensions();
+ if (this.currentType.isArrayType()) {
+ this.dimensions += ((ArrayType) this.currentType).getDimensions();
+ }
+ }
+
+ RecoveredTypeBinding(BindingResolver resolver, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+ this.resolver = resolver;
+ this.dimensions = referenceBinding.dimensions();
+ this.referenceBinding = referenceBinding;
+ }
+
+ RecoveredTypeBinding(BindingResolver resolver, Type type) {
+ this.currentType = type;
+ this.resolver = resolver;
+ this.dimensions = 0;
+ if (type.isArrayType()) {
+ this.dimensions += ((ArrayType) type).getDimensions();
+ }
+ }
+
+ RecoveredTypeBinding(BindingResolver resolver, RecoveredTypeBinding typeBinding, int dimensions) {
+ this.innerTypeBinding = typeBinding;
+ this.dimensions = typeBinding.getDimensions() + dimensions;
+ this.resolver = resolver;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#createArrayType(int)
+ */
+ public ITypeBinding createArrayType(int dims) {
+ return this.resolver.getTypeBinding(this, dims);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getBinaryName()
+ */
+ public String getBinaryName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getBound()
+ */
+ public ITypeBinding getBound() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getComponentType()
+ */
+ public ITypeBinding getComponentType() {
+ if (this.dimensions == 0) return null;
+ return this.resolver.getTypeBinding(this, -1);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDeclaredFields()
+ */
+ public IVariableBinding[] getDeclaredFields() {
+ return TypeBinding.NO_VARIABLE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDeclaredMethods()
+ */
+ public IFunctionBinding[] getDeclaredMethods() {
+ return TypeBinding.NO_METHOD_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDeclaredModifiers()
+ */
+ public int getDeclaredModifiers() {
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDeclaredTypes()
+ */
+ public ITypeBinding[] getDeclaredTypes() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDeclaringMethod()
+ */
+ public IFunctionBinding getDeclaringMethod() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getDimensions()
+ */
+ public int getDimensions() {
+ return this.dimensions;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getElementType()
+ */
+ public ITypeBinding getElementType() {
+ if (this.referenceBinding != null) {
+ if (this.referenceBinding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) this.referenceBinding;
+ return new RecoveredTypeBinding(this.resolver, arrayBinding.leafComponentType);
+ } else {
+ return new RecoveredTypeBinding(this.resolver, this.referenceBinding);
+ }
+ }
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getElementType();
+ }
+ if (this.currentType!= null && this.currentType.isArrayType()) {
+ return this.resolver.getTypeBinding(((ArrayType) this.currentType).getElementType());
+ }
+ if (this.variableDeclaration != null && this.variableDeclaration.getExtraDimensions() != 0) {
+ return this.resolver.getTypeBinding(getType());
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getErasure()
+ */
+ public ITypeBinding getErasure() {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getInterfaces()
+ */
+ public ITypeBinding[] getInterfaces() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getModifiers()
+ */
+ public int getModifiers() {
+ return Modifier.NONE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getName()
+ */
+ public String getName() {
+ char[] brackets = new char[this.dimensions * 2];
+ for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ StringBuffer buffer = new StringBuffer(this.getInternalName());
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+ }
+
+ private String getInternalName() {
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getInternalName();
+ } else if (this.referenceBinding != null) {
+ org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding typeBinding = null;
+ if (this.referenceBinding.isArrayType()) {
+ ArrayBinding arrayBinding = (ArrayBinding) this.referenceBinding;
+ if (arrayBinding.leafComponentType instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding) {
+ typeBinding = (org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding) arrayBinding.leafComponentType;
+ }
+ } else if (this.referenceBinding instanceof org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding) {
+ typeBinding = (org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding) this.referenceBinding;
+ }
+ return new String(typeBinding.compoundName[typeBinding.compoundName.length - 1]);
+ }
+ return this.getTypeNameFrom(getType());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getPackage()
+ */
+ public IPackageBinding getPackage() {
+ CompilationUnitScope scope = this.resolver.scope();
+ if (scope != null) {
+ return this.resolver.getPackageBinding(scope.getCurrentPackage());
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getQualifiedName()
+ */
+ public String getQualifiedName() {
+ return this.getName();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getSuperclass()
+ */
+ public ITypeBinding getSuperclass() {
+ return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeArguments()
+ */
+ public ITypeBinding[] getTypeArguments() {
+ if (this.referenceBinding != null) {
+ return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+ }
+ if (this.typeArguments != null) {
+ return typeArguments;
+ }
+
+ if (this.innerTypeBinding != null) {
+ return this.innerTypeBinding.getTypeArguments();
+ }
+
+ return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeBounds()
+ */
+ public ITypeBinding[] getTypeBounds() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeDeclaration()
+ */
+ public ITypeBinding getTypeDeclaration() {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeParameters()
+ */
+ public ITypeBinding[] getTypeParameters() {
+ return TypeBinding.NO_TYPE_BINDINGS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isAnnotation()
+ */
+ public boolean isAnnotation() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isAnonymous()
+ */
+ public boolean isAnonymous() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isArray()
+ */
+ public boolean isArray() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isAssignmentCompatible(org.eclipse.wst.jsdt.core.dom.ITypeBinding)
+ */
+ public boolean isAssignmentCompatible(ITypeBinding typeBinding) {
+ if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+ return true;
+ }
+ // since recovered binding are not unique isEqualTo is required
+ return this.isEqualTo(typeBinding);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isCapture()
+ */
+ public boolean isCapture() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isCastCompatible(org.eclipse.wst.jsdt.core.dom.ITypeBinding)
+ */
+ public boolean isCastCompatible(ITypeBinding typeBinding) {
+ if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+ return true;
+ }
+ // since recovered binding are not unique isEqualTo is required
+ return this.isEqualTo(typeBinding);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isClass()
+ */
+ public boolean isClass() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isEnum()
+ */
+ public boolean isEnum() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isFromSource()
+ */
+ public boolean isFromSource() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isGenericType()
+ */
+ public boolean isGenericType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isInterface()
+ */
+ public boolean isInterface() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isLocal()
+ */
+ public boolean isLocal() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isMember()
+ */
+ public boolean isMember() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isNested()
+ */
+ public boolean isNested() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isNullType()
+ */
+ public boolean isNullType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isPrimitive()
+ */
+ public boolean isPrimitive() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isRawType()
+ */
+ public boolean isRawType() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isSubTypeCompatible(org.eclipse.wst.jsdt.core.dom.ITypeBinding)
+ */
+ public boolean isSubTypeCompatible(ITypeBinding typeBinding) {
+ if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+ return true;
+ }
+ // since recovered binding are not unique isEqualTo is required
+ return this.isEqualTo(typeBinding);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isTopLevel()
+ */
+ public boolean isTopLevel() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isTypeVariable()
+ */
+ public boolean isTypeVariable() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#isUpperbound()
+ */
+ public boolean isUpperbound() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#getJavaElement()
+ */
+ public IJavaScriptElement getJavaElement() {
+ try {
+ return new CompilationUnit(null, this.getInternalName(), this.resolver.getWorkingCopyOwner()).getWorkingCopy(this.resolver.getWorkingCopyOwner(), null);
+ } catch (JavaScriptModelException e) {
+ //ignore
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#getKey()
+ */
+ public String getKey() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Recovered#"); //$NON-NLS-1$
+ if (this.innerTypeBinding != null) {
+ buffer.append("innerTypeBinding") //$NON-NLS-1$
+ .append(this.innerTypeBinding.getKey());
+ } else if (this.currentType != null) {
+ buffer.append("currentType") //$NON-NLS-1$
+ .append(this.currentType.toString());
+ } else if (this.referenceBinding != null) {
+ buffer.append("referenceBinding") //$NON-NLS-1$
+ .append(this.referenceBinding.computeUniqueKey());
+ } else if (variableDeclaration != null) {
+ buffer
+ .append("variableDeclaration") //$NON-NLS-1$
+ .append(this.variableDeclaration.getClass())
+ .append(this.variableDeclaration.getName().getIdentifier())
+ .append(this.variableDeclaration.getExtraDimensions());
+ }
+ buffer.append(this.getDimensions());
+ if (this.typeArguments != null) {
+ buffer.append('<');
+ for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+ if (i != 0) {
+ buffer.append(',');
+ }
+ buffer.append(this.typeArguments[i].getKey());
+ }
+ buffer.append('>');
+ }
+ return String.valueOf(buffer);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.TYPE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#isEqualTo(org.eclipse.wst.jsdt.core.dom.IBinding)
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (!other.isRecovered() || other.getKind() != IBinding.TYPE) return false;
+ return this.getKey().equals(other.getKey());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return true;
+ }
+
+ private String getTypeNameFrom(Type type) {
+ if (type == null) return Util.EMPTY_STRING;
+ switch(type.getNodeType0()) {
+ case ASTNode.ARRAY_TYPE :
+ ArrayType arrayType = (ArrayType) type;
+ type = arrayType.getElementType();
+ return getTypeNameFrom(type);
+ case ASTNode.PRIMITIVE_TYPE :
+ PrimitiveType primitiveType = (PrimitiveType) type;
+ return primitiveType.getPrimitiveTypeCode().toString();
+ case ASTNode.QUALIFIED_TYPE :
+ QualifiedType qualifiedType = (QualifiedType) type;
+ return qualifiedType.getName().getIdentifier();
+ case ASTNode.SIMPLE_TYPE :
+ SimpleType simpleType = (SimpleType) type;
+ Name name = simpleType.getName();
+ if (name.isQualifiedName()) {
+ QualifiedName qualifiedName = (QualifiedName) name;
+ return qualifiedName.getName().getIdentifier();
+ }
+ return ((SimpleName) name).getIdentifier();
+ }
+ return Util.EMPTY_STRING;
+ }
+
+ private Type getType() {
+ if (this.currentType != null) {
+ return this.currentType;
+ }
+ if (this.variableDeclaration == null) return null;
+ switch(this.variableDeclaration.getNodeType()) {
+ case ASTNode.SINGLE_VARIABLE_DECLARATION :
+ SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) this.variableDeclaration;
+ return singleVariableDeclaration.getType();
+ default :
+ // this is a variable declaration fragment
+ ASTNode parent = this.variableDeclaration.getParent();
+ switch(parent.getNodeType()) {
+ case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+ VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) parent;
+ return variableDeclarationExpression.getType();
+ case ASTNode.VARIABLE_DECLARATION_STATEMENT :
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) parent;
+ return statement.getType();
+ case ASTNode.FIELD_DECLARATION :
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) parent;
+ return fieldDeclaration.getType();
+ }
+ }
+ return null; // should not happen
+ }
+
+ public boolean isCompilationUnit() {
+ return false;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RecoveredVariableBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RecoveredVariableBinding.java
new file mode 100644
index 0000000..cefea49
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RecoveredVariableBinding.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * This class represents the recovered binding for a variable
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+class RecoveredVariableBinding implements IVariableBinding {
+
+ private VariableDeclaration variableDeclaration;
+ private BindingResolver resolver;
+
+ RecoveredVariableBinding(BindingResolver resolver, VariableDeclaration variableDeclaration) {
+ this.resolver = resolver;
+ this.variableDeclaration = variableDeclaration;
+ }
+ public Object getConstantValue() {
+ return null;
+ }
+
+ public ITypeBinding getDeclaringClass() {
+ ASTNode parent = this.variableDeclaration.getParent();
+ while (parent != null && parent.getNodeType() != ASTNode.TYPE_DECLARATION) {
+ parent = parent.getParent();
+ }
+ if (parent != null) {
+ return ((TypeDeclaration) parent).resolveBinding();
+ }
+ return null;
+ }
+
+ public IFunctionBinding getDeclaringMethod() {
+ ASTNode parent = this.variableDeclaration.getParent();
+ while (parent != null && parent.getNodeType() != ASTNode.FUNCTION_DECLARATION) {
+ parent = parent.getParent();
+ }
+ if (parent != null) {
+ return ((FunctionDeclaration) parent).resolveBinding();
+ }
+ return null;
+ }
+
+ public String getName() {
+ return this.variableDeclaration.getName().getIdentifier();
+ }
+
+ public ITypeBinding getType() {
+ return this.resolver.getTypeBinding(this.variableDeclaration);
+ }
+
+ public IVariableBinding getVariableDeclaration() {
+ return this;
+ }
+
+ public int getVariableId() {
+ return 0;
+ }
+
+ public boolean isEnumConstant() {
+ return false;
+ }
+
+ public boolean isField() {
+ return this.variableDeclaration.getParent() instanceof FieldDeclaration;
+ }
+
+ public boolean isParameter() {
+ return this.variableDeclaration instanceof SingleVariableDeclaration;
+ }
+
+ public IJavaScriptElement getJavaElement() {
+ return null;
+ }
+
+ public String getKey() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Recovered#"); //$NON-NLS-1$
+ if (variableDeclaration != null) {
+ buffer
+ .append("variableDeclaration") //$NON-NLS-1$
+// .append(this.variableDeclaration.getClass())
+ .append(this.variableDeclaration.getName().getIdentifier())
+ .append(this.variableDeclaration.getExtraDimensions());
+ }
+ return String.valueOf(buffer);
+ }
+
+ public int getKind() {
+ return IBinding.VARIABLE;
+ }
+
+ public int getModifiers() {
+ return 0;
+ }
+
+ public boolean isDeprecated() {
+ return false;
+ }
+
+ public boolean isEqualTo(IBinding binding) {
+ if (binding.isRecovered() && binding.getKind() == IBinding.VARIABLE) {
+ return this.getKey().equals(binding.getKey());
+ }
+ return false;
+ }
+
+ public boolean isRecovered() {
+ return true;
+ }
+
+ public boolean isGlobal() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RegularExpressionLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RegularExpressionLiteral.java
new file mode 100644
index 0000000..5022950
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/RegularExpressionLiteral.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public class RegularExpressionLiteral extends Expression {
+
+ /**
+ * The "escapedValue" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor REGULAR_EXPRESSION_PROPERTY =
+ new SimplePropertyDescriptor(RegularExpressionLiteral.class, "regularExpression", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List properyList = new ArrayList(2);
+ createPropertyList(RegularExpressionLiteral.class, properyList);
+ addProperty(REGULAR_EXPRESSION_PROPERTY, properyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+ // includes '/'
+ private String regularExpression = "/&/g";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented character literal node owned by the given AST.
+ * By default, the character literal denotes an unspecified character.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ RegularExpressionLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == REGULAR_EXPRESSION_PROPERTY) {
+ if (get) {
+ return getRegularExpression();
+ } else {
+ setRegularExpression((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return REGULAR_EXPRESSION_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ RegularExpressionLiteral result = new RegularExpressionLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setRegularExpression(getRegularExpression());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the string value of this literal node. The value is the sequence
+ * of characters that would appear in the source program, including
+ * enclosing single quotes and embedded escapes.
+ *
+ * @return the escaped string value, including enclosing single quotes
+ * and embedded escapes
+ */
+ public String getRegularExpression() {
+ return this.regularExpression;
+ }
+
+ /**
+ * Sets the string value of this literal node. The value is the sequence
+ * of characters that would appear in the source program, including
+ * enclosing single quotes and embedded escapes. For example,
+ *
+ * 'a'
setEscapedValue("\'a\'")
+ * '\n'
setEscapedValue("\'\\n\'")
+ *
+ *
+ * @param value the string value, including enclosing single quotes
+ * and embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setRegularExpression(String value) {
+ // check setInternalEscapedValue(String) if this method is changed
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = value.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameRegExLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(REGULAR_EXPRESSION_PROPERTY);
+ this.regularExpression = value;
+ postValueChange(REGULAR_EXPRESSION_PROPERTY);
+ }
+
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+ */
+ void internalSetRegularExpression(String value) {
+ preValueChange(REGULAR_EXPRESSION_PROPERTY);
+ this.regularExpression = value;
+ postValueChange(REGULAR_EXPRESSION_PROPERTY);
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(regularExpression);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ReturnStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ReturnStatement.java
new file mode 100644
index 0000000..c24da2c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ReturnStatement.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Return statement AST node type.
+ *
+ *
+ * ReturnStatement:
+ * return [ Expression ] ;
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public class ReturnStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ReturnStatement.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ReturnStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; null
for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * Creates a new AST node for a return statement owned by the
+ * given AST. By default, the statement has no expression.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ReturnStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return RETURN_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ReturnStatement result = new ReturnStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this return statement, or
+ * null
if there is none.
+ *
+ * @return the expression node, or null
if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets or clears the expression of this return statement.
+ *
+ * @param expression the expression node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimpleName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimpleName.java
new file mode 100644
index 0000000..9babc64
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimpleName.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * AST node for a simple name. A simple name is an identifier other than
+ * a keyword, boolean literal ("true", "false") or null literal ("null").
+ *
+ * SimpleName:
+ * Identifier
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SimpleName extends Name {
+
+ /**
+ * The "identifier" structural property of this node type.
+ *
+ *
+ */
+ public static final SimplePropertyDescriptor IDENTIFIER_PROPERTY =
+ new SimplePropertyDescriptor(SimpleName.class, "identifier", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(SimpleName.class, propertyList);
+ addProperty(IDENTIFIER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the AST.JLS* constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * An unspecified (but externally observable) legal JavaScript identifier.
+ */
+ private static final String MISSING_IDENTIFIER = "MISSING";//$NON-NLS-1$
+
+ /**
+ * The identifier; defaults to a unspecified, legal JavaScript identifier.
+ */
+ private String identifier = MISSING_IDENTIFIER;
+
+ /**
+ * Creates a new AST node for a simple name owned by the given AST.
+ * The new node has an unspecified, legal JavaScript identifier.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ SimpleName(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == IDENTIFIER_PROPERTY) {
+ if (get) {
+ return getIdentifier();
+ } else {
+ setIdentifier((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SIMPLE_NAME;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SimpleName result = new SimpleName(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setIdentifier(getIdentifier());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns this node's identifier.
+ *
+ * @return the identifier of this node
+ */
+ public String getIdentifier() {
+ return this.identifier;
+ }
+
+ /**
+ * Sets the identifier of this node to the given value.
+ * The identifier should be legal according to the rules
+ * of the JavaScript language. Note that keywords are not legal
+ * identifiers.
+ *
+ * Note that the list of keywords may depend on the version of the
+ * language (determined when the AST object was created).
+ *
+ *
+ * @param identifier the identifier of this node
+ * @exception IllegalArgumentException if the identifier is invalid
+ */
+ public void setIdentifier(String identifier) {
+ // update internalSetIdentifier if this is changed
+ if (identifier == null) {
+ throw new IllegalArgumentException();
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = identifier.toCharArray();
+ scanner.setSource(source);
+ final int length = source.length;
+ scanner.resetTo(0, length - 1);
+ try {
+ int tokenType = scanner.scanIdentifier();
+ if (tokenType != TerminalTokens.TokenNameIdentifier) {
+ throw new IllegalArgumentException();
+ }
+ if (scanner.currentPosition != length) {
+ // this is the case when there is only one identifier see 87849
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(IDENTIFIER_PROPERTY);
+ this.identifier = identifier;
+ postValueChange(IDENTIFIER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setIdentifier(String) that doesn't do any validation.
+ */
+ void internalSetIdentifier(String ident) {
+ preValueChange(IDENTIFIER_PROPERTY);
+ this.identifier = ident;
+ postValueChange(IDENTIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns whether this simple name represents a name that is being defined,
+ * as opposed to one being referenced. The following positions are considered
+ * ones where a name is defined:
+ *
+ * - The type name in a
TypeDeclaration
node.
+ * - The method name in a
FunctionDeclaration
node
+ * providing isConstructor
is false
.
+ * - The variable name in any type of
VariableDeclaration
+ * node.
+ * - The enum type name in a
EnumDeclaration
node.
+ * - The enum constant name in an
EnumConstantDeclaration
+ * node.
+ * - The variable name in an
EnhancedForStatement
+ * node.
+ * - The type variable name in a
TypeParameter
+ * node.
+ * - The type name in an
AnnotationTypeDeclaration
node.
+ * - The member name in an
AnnotationTypeMemberDeclaration
node.
+ *
+ *
+ * Note that this is a convenience method that simply checks whether
+ * this node appears in the declaration position relative to its parent.
+ * It always returns false
if this node is unparented.
+ *
+ *
+ * @return true
if this node declares a name, and
+ * false
otherwise
+ */
+ public boolean isDeclaration() {
+ StructuralPropertyDescriptor d = getLocationInParent();
+ if (d == null) {
+ // unparented node
+ return false;
+ }
+ ASTNode parent = getParent();
+ if (parent instanceof TypeDeclaration) {
+ return (d == TypeDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof FunctionDeclaration) {
+ FunctionDeclaration p = (FunctionDeclaration) parent;
+ // could be the name of the method or constructor
+ return !p.isConstructor() && (d == FunctionDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof SingleVariableDeclaration) {
+ return (d == SingleVariableDeclaration.NAME_PROPERTY);
+ }
+ if (parent instanceof VariableDeclarationFragment) {
+ return (d == VariableDeclarationFragment.NAME_PROPERTY);
+ }
+
+ return false;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on Name.
+ */
+ void appendName(StringBuffer buffer) {
+ buffer.append(getIdentifier());
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NAME_NODE_SIZE + 2 * 4;
+ if (identifier != MISSING_IDENTIFIER) {
+ // everything but our missing id costs
+ size += stringSize(identifier);
+ }
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimplePropertyDescriptor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimplePropertyDescriptor.java
new file mode 100644
index 0000000..82790ad
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimplePropertyDescriptor.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Descriptor for a simple property of an AST node.
+ * A simple property is one whose value is a
+ * primitive type (such as int
or boolean
)
+ * or some simple value type (such as String
or
+ * InfixExpression.Operator
).
+ *
+ * @see org.eclipse.wst.jsdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @see org.eclipse.wst.jsdt.core.dom.ASTNode#setStructuralProperty(StructuralPropertyDescriptor, Object)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class SimplePropertyDescriptor extends StructuralPropertyDescriptor {
+
+ /**
+ * Value type. For example, for a node type like
+ * SingleVariableDeclaration, the modifiers property is int.class
+ */
+ private final Class valueType;
+
+ /**
+ * Indicates whether a value is mandatory. A property value is allowed
+ * to be null
only if it is not mandatory.
+ */
+ private final boolean mandatory;
+
+ /**
+ * Creates a new simple property descriptor with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ * @param valueType the value type of this property
+ * @param mandatory true
if the property is mandatory,
+ * and false
if it is may be null
+ */
+ SimplePropertyDescriptor(Class nodeClass, String propertyId, Class valueType, boolean mandatory) {
+ super(nodeClass, propertyId);
+ if (valueType == null || ASTNode.class.isAssignableFrom(valueType)) {
+ throw new IllegalArgumentException();
+ }
+ this.valueType = valueType;
+ this.mandatory = mandatory;
+ }
+
+ /**
+ * Returns the value type of this property.
+ *
+ * For example, for a node type like SingleVariableDeclaration,
+ * the "modifiers" property returns int.class
.
+ *
+ *
+ * @return the value type of the property
+ */
+ public Class getValueType() {
+ return this.valueType;
+ }
+
+ /**
+ * Returns whether this property is mandatory. A property value
+ * is not allowed to be null
if it is mandatory.
+ *
+ * @return true
if the property is mandatory,
+ * and false
if it is may be null
+ */
+ public boolean isMandatory() {
+ return this.mandatory;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimpleType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimpleType.java
new file mode 100644
index 0000000..52ba66f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SimpleType.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a named class type, a named interface type, or a type variable.
+ *
+ * This kind of node is used to convert a name (Name
) into a type
+ * (Type
) by wrapping it.
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public class SimpleType extends Type {
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SimpleType.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(SimpleType.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type name node; lazily initialized; defaults to a type with
+ * an unspecfied, but legal, name.
+ */
+ private Name typeName = null;
+
+ /**
+ * Creates a new unparented node for a simple type owned by the given AST.
+ * By default, an unspecified, but legal, name.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ SimpleType(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SIMPLE_TYPE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SimpleType result = new SimpleType(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((Name) (getName()).clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of this simple type.
+ *
+ * @return the name of this simple type
+ */
+ public Name getName() {
+ if (this.typeName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeName == null) {
+ preLazyInit();
+ this.typeName = new SimpleName(this.ast);
+ postLazyInit(this.typeName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.typeName;
+ }
+
+ /**
+ * Sets the name of this simple type to the given name.
+ *
+ * @param typeName the new name of this simple type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(Name typeName) {
+ if (typeName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.typeName;
+ preReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ this.typeName = typeName;
+ postReplaceChild(oldChild, typeName, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SingleVariableDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SingleVariableDeclaration.java
new file mode 100644
index 0000000..3999e15
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SingleVariableDeclaration.java
@@ -0,0 +1,641 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Single variable declaration AST node type. Single variable
+ * declaration nodes are used in a limited number of places, including formal
+ * parameter lists and catch clauses. They are not used for field declarations
+ * and regular variable declaration statements.
+ * For JLS2:
+ *
+ * SingleVariableDeclaration:
+ * { Modifier } Type Identifier { [] } [ = Expression ]
+ *
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations), and the variable arity
+ * indicator was added:
+ *
+ * SingleVariableDeclaration:
+ * { ExtendedModifier } Type [ ... ] Identifier { [] } [ = Expression ]
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SingleVariableDeclaration extends VariableDeclaration {
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ new SimplePropertyDescriptor(SingleVariableDeclaration.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ new ChildListPropertyDescriptor(SingleVariableDeclaration.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SingleVariableDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(SingleVariableDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "varargs" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final SimplePropertyDescriptor VARARGS_PROPERTY =
+ new SimplePropertyDescriptor(SingleVariableDeclaration.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "extraDimensions" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
+ new SimplePropertyDescriptor(SingleVariableDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "initializer" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(SingleVariableDeclaration.class, "initializer", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(6);
+ createPropertyList(SingleVariableDeclaration.class, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(INITIALIZER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(7);
+ createPropertyList(SingleVariableDeclaration.class, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(VARARGS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(INITIALIZER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The extended modifiers (element type: IExtendedModifier
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ *
+ */
+ private ASTNode.NodeList modifiers = null;
+
+ /**
+ * The modifiers; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in 3.0.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The variable name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript identifier.
+ */
+ private SimpleName variableName = null;
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * Indicates the last parameter of a variable arity method;
+ * defaults to false.
+ *
+ *
+ */
+ private boolean variableArity = false;
+
+ /**
+ * The number of extra array dimensions that appear after the variable;
+ * defaults to 0.
+ *
+ *
+ */
+ private int extraArrayDimensions = 0;
+
+ /**
+ * The initializer expression, or null
if none;
+ * defaults to none.
+ */
+ private Expression optionalInitializer = null;
+
+ /**
+ * Creates a new AST node for a variable declaration owned by the given
+ * AST. By default, the variable declaration has: no modifiers, an
+ * unspecified (but legal) type, an unspecified (but legal) variable name,
+ * 0 dimensions after the variable; no initializer; not variable arity.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ SingleVariableDeclaration(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+ return EXTRA_DIMENSIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ final ChildPropertyDescriptor internalInitializerProperty() {
+ return INITIALIZER_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ if (property == EXTRA_DIMENSIONS_PROPERTY) {
+ if (get) {
+ return getExtraDimensions();
+ } else {
+ setExtraDimensions(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ if (property == VARARGS_PROPERTY) {
+ if (get) {
+ return isVarargs();
+ } else {
+ setVarargs(value);
+ return false;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SINGLE_VARIABLE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SingleVariableDeclaration result = new SingleVariableDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setModifiers(getModifiers());
+ } else {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setVarargs(isVarargs());
+ }
+ result.setType((Type) getType().clone(target));
+ result.setExtraDimensions(getExtraDimensions());
+ result.setName((SimpleName) getName().clone(target));
+ result.setInitializer(
+ (Expression) ASTNode.copySubtree(target, getInitializer()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ *
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable and formal parameter declarations.
+ *
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: IExtendedModifier
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ *
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from modifiers()
.
+ *
+ *
+ * @return the bit-wise or of Modifier
constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenient method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedModifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedModifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ *
+ * The following modifiers are meaningful for fields: public, private, protected,
+ * static, final, volatile, and transient. For local variable and formal
+ * parameter declarations, the only meaningful modifier is final.
+ *
+ *
+ * @param modifiers the given modifiers (bit-wise or of Modifier
constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a Modifier
nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ supportedOnlyIn2();
+ preValueChange(MODIFIERS_PROPERTY);
+ this.modifierFlags = pmodifiers;
+ postValueChange(MODIFIERS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public SimpleName getName() {
+ if (this.variableName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.variableName == null) {
+ preLazyInit();
+ this.variableName = new SimpleName(this.ast);
+ postLazyInit(this.variableName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.variableName;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setName(SimpleName variableName) {
+ if (variableName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.variableName;
+ preReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ this.variableName = variableName;
+ postReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the type of the variable declared in this variable declaration,
+ * exclusive of any extra array dimensions.
+ *
+ * @return the type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newInferredType(null);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type of the variable declared in this variable declaration to
+ * the given type, exclusive of any extra array dimensions.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ return;
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ if (type instanceof InferredType && ((InferredType)type).getType()==null)
+ this.type=null;
+ else
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns whether this declaration declares the last parameter of
+ * a variable arity method (added in JLS3 API).
+ *
+ * Note that the binding for the type Foo
in the vararg method
+ * declaration void fun(Foo... args)
is always for the type as
+ * written; i.e., the type binding for Foo
. However, if you
+ * navigate from the method declaration to its method binding to the
+ * type binding for its last parameter, the type binding for the vararg
+ * parameter is always an array type (i.e., Foo[]
) reflecting
+ * the way vararg methods get compiled.
+ *
+ *
+ * @return true
if this is a variable arity parameter declaration,
+ * and false
otherwise
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public boolean isVarargs() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.variableArity;
+ }
+
+ /**
+ * Sets whether this declaration declares the last parameter of
+ * a variable arity method (added in JLS3 API).
+ *
+ * @param variableArity true
if this is a variable arity
+ * parameter declaration, and false
otherwise
+ *
+ */
+ public void setVarargs(boolean variableArity) {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ preValueChange(VARARGS_PROPERTY);
+ this.variableArity = variableArity;
+ postValueChange(VARARGS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ public int getExtraDimensions() {
+ return this.extraArrayDimensions;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ public void setExtraDimensions(int dimensions) {
+ if (dimensions < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ this.extraArrayDimensions = dimensions;
+ postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public Expression getInitializer() {
+ return this.optionalInitializer;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setInitializer(Expression initializer) {
+ // a SingleVariableDeclaration may occur inside an Expression
+ // must check cycles
+ ASTNode oldChild = this.optionalInitializer;
+ preReplaceChild(oldChild, initializer,INITIALIZER_PROPERTY);
+ this.optionalInitializer = initializer;
+ postReplaceChild(oldChild, initializer,INITIALIZER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 7 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.type == null ? 0 : getType().treeSize())
+ + (this.variableName == null ? 0 : getName().treeSize())
+ + (this.optionalInitializer == null ? 0 : getInitializer().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Statement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Statement.java
new file mode 100644
index 0000000..c5ecf7b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Statement.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Abstract base class of AST nodes that represent statements.
+ * There are many kinds of statements.
+ *
+ * The grammar combines both Statement and BlockStatement.
+ * For JLS2:
+ *
+ * Statement:
+ * Block
+ * IfStatement
+ * ForStatement
+ * WhileStatement
+ * DoStatement
+ * TryStatement
+ * SwitchStatement
+ * SynchronizedStatement
+ * ReturnStatement
+ * ThrowStatement
+ * BreakStatement
+ * ContinueStatement
+ * EmptyStatement
+ * ExpressionStatement
+ * LabeledStatement
+ * AssertStatement
+ * VariableDeclarationStatement
+ * TypeDeclarationStatement
+ * ConstructorInvocation
+ * SuperConstructorInvocation
+ *
+ * For JLS3, an enhanced for node type was added:
+ *
+ * Statement:
+ * Block
+ * IfStatement
+ * ForStatement
+ * EnhancedForStatement
+ * WhileStatement
+ * DoStatement
+ * TryStatement
+ * SwitchStatement
+ * SynchronizedStatement
+ * ReturnStatement
+ * ThrowStatement
+ * BreakStatement
+ * ContinueStatement
+ * EmptyStatement
+ * ExpressionStatement
+ * LabeledStatement
+ * AssertStatement
+ * VariableDeclarationStatement
+ * TypeDeclarationStatement
+ * ConstructorInvocation
+ * SuperConstructorInvocation
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class Statement extends ProgramElement {
+
+ /**
+ * The leading comment, or null
if none.
+ * Defaults to none.
+ *
+ * @deprecated The leading comment feature was removed in 2.1.
+ */
+ private String optionalLeadingComment = null;
+
+ /**
+ * Creates a new AST node for a statement owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Statement(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns the leading comment string, including the starting
+ * and ending comment delimiters, and any embedded line breaks.
+ *
+ * A leading comment is a comment that appears before the statement.
+ * It may be either a traditional comment or an end-of-line comment.
+ * Traditional comments must begin with "/*, may contain line breaks,
+ * and must end with "*/. End-of-line comments must begin with "//",
+ * must end with a line delimiter (as per JLS 3.7), and must not contain
+ * line breaks.
+ *
+ *
+ * @return the comment string, or null
if none
+ * @deprecated This feature was removed in the 2.1 release because it was
+ * only a partial, and inadequate, solution to the issue of associating
+ * comments with statements. Furthermore, AST.parseCompilationUnit did not
+ * associate leading comments, making this moot. Clients that need to access
+ * comments preceding a statement should either consult the compilation
+ * unit's {@linkplain JavaScriptUnit#getCommentList() comment table}
+ * or use a scanner to reanalyze the source text immediately preceding
+ * the statement's source range.
+ */
+ public String getLeadingComment() {
+ return optionalLeadingComment;
+ }
+
+ /**
+ * Sets or clears the leading comment string. The comment
+ * string must include the starting and ending comment delimiters,
+ * and any embedded linebreaks.
+ *
+ * A leading comment is a comment that appears before the statement.
+ * It may be either a traditional comment or an end-of-line comment.
+ * Traditional comments must begin with "/*, may contain line breaks,
+ * and must end with "*/. End-of-line comments must begin with "//"
+ * (as per JLS 3.7), and must not contain line breaks.
+ *
+ *
+ * Examples:
+ *
+ *
+ * setLeadingComment("/* traditional comment */"); // correct
+ * setLeadingComment("missing comment delimiters"); // wrong
+ * setLeadingComment("/* unterminated traditional comment "); // wrong
+ * setLeadingComment("/* broken\n traditional comment */"); // correct
+ * setLeadingComment("// end-of-line comment\n"); // correct
+ * setLeadingComment("// end-of-line comment without line terminator"); // correct
+ * setLeadingComment("// broken\n end-of-line comment\n"); // wrong
+ *
+ *
+ *
+ *
+ * @param comment the comment string, or null
if none
+ * @exception IllegalArgumentException if the comment string is invalid
+ * @deprecated This feature was removed in the 2.1 release because it was
+ * only a partial, and inadequate, solution to the issue of associating
+ * comments with statements.
+ */
+ public void setLeadingComment(String comment) {
+ if (comment != null) {
+ char[] source = comment.toCharArray();
+ Scanner scanner = this.ast.scanner;
+ scanner.resetTo(0, source.length);
+ scanner.setSource(source);
+ try {
+ int token;
+ boolean onlyOneComment = false;
+ while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ switch(token) {
+ case TerminalTokens.TokenNameCOMMENT_BLOCK :
+ case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+ case TerminalTokens.TokenNameCOMMENT_LINE :
+ if (onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ onlyOneComment = true;
+ break;
+ default:
+ onlyOneComment = false;
+ }
+ }
+ if (!onlyOneComment) {
+ throw new IllegalArgumentException();
+ }
+ } catch (InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ }
+ // we do not consider the obsolete comment as a structureal property
+ // but we protect them nevertheless
+ checkModifiable();
+ this.optionalLeadingComment = comment;
+ }
+
+ /**
+ * Copies the leading comment from the given statement.
+ *
+ * @param source the statement that supplies the leading comment
+ *
+ */
+ void copyLeadingComment(Statement source) {
+ setLeadingComment(source.getLeadingComment());
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(getLeadingComment());
+ return size;
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/StringLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/StringLiteral.java
new file mode 100644
index 0000000..d522075
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/StringLiteral.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * String literal nodes.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class StringLiteral extends Expression {
+
+ /**
+ * The "escapedValue" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
+ new SimplePropertyDescriptor(StringLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(StringLiteral.class, propertyList);
+ addProperty(ESCAPED_VALUE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The literal string, including quotes and escapes; defaults to the
+ * literal for the empty string.
+ */
+ private String escapedValue = "\"\"";//$NON-NLS-1$
+
+ /**
+ * Creates a new unparented string literal node owned by the given AST.
+ * By default, the string literal denotes the empty string.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ StringLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == ESCAPED_VALUE_PROPERTY) {
+ if (get) {
+ return getEscapedValue();
+ } else {
+ setEscapedValue((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return STRING_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ StringLiteral result = new StringLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setEscapedValue(getEscapedValue());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the string value of this literal node to the given string
+ * literal token. The token is the sequence of characters that would appear
+ * in the source program, including enclosing double quotes and embedded
+ * escapes.
+ *
+ * @return the string literal token, including enclosing double
+ * quotes and embedded escapes
+ */
+ public String getEscapedValue() {
+ return this.escapedValue;
+ }
+
+ /**
+ * Sets the string value of this literal node to the given string literal
+ * token. The token is the sequence of characters that would appear in the
+ * source program, including enclosing double quotes and embedded escapes.
+ * For example,
+ *
+ * ""
setLiteral("\"\"")
+ * "hello world"
setLiteral("\"hello world\"")
+ * "boo\nhoo"
setLiteral("\"boo\\nhoo\"")
+ *
+ *
+ * @param token the string literal token, including enclosing double
+ * quotes and embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setEscapedValue(String token) {
+ // update internalSetEscapedValue(String) if this is changed
+ if (token == null) {
+ throw new IllegalArgumentException("Token cannot be null"); //$NON-NLS-1$
+ }
+ Scanner scanner = this.ast.scanner;
+ char[] source = token.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameStringLiteral:
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid string literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException("Invalid string literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
+ }
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = token;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+ */
+ void internalSetEscapedValue(String token) {
+ preValueChange(ESCAPED_VALUE_PROPERTY);
+ this.escapedValue = token;
+ postValueChange(ESCAPED_VALUE_PROPERTY);
+ }
+
+ /**
+ * Returns the value of this literal node.
+ *
+ * For example,
+ *
+ * StringLiteral s;
+ * s.setEscapedValue("\"hello\\nworld\"");
+ * assert s.getLiteralValue().equals("hello\nworld");
+ *
+ *
+ *
+ * Note that this is a convenience method that converts from the stored
+ * string literal token returned by getEscapedLiteral
.
+ *
+ *
+ * @return the string value without enclosing double quotes and embedded
+ * escapes
+ * @exception IllegalArgumentException if the literal value cannot be converted
+ */
+ public String getLiteralValue() {
+ String s = getEscapedValue();
+ int len = s.length();
+ if (len < 2 || s.charAt(0) != '\"' || s.charAt(len-1) != '\"' ) {
+ throw new IllegalArgumentException();
+ }
+
+ Scanner scanner = this.ast.scanner;
+ char[] source = s.toCharArray();
+ scanner.setSource(source);
+ scanner.resetTo(0, source.length);
+ try {
+ int tokenType = scanner.getNextToken();
+ switch(tokenType) {
+ case TerminalTokens.TokenNameStringLiteral:
+ return scanner.getCurrentStringLiteral();
+ default:
+ throw new IllegalArgumentException();
+ }
+ } catch(InvalidInputException e) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Sets the value of this literal node.
+ *
+ * For example,
+ *
+ * StringLiteral s;
+ * s.setLiteralValue("hello\nworld");
+ * assert s.getEscapedValue("\"hello\\nworld\"");
+ * assert s.getLiteralValue().equals("hello\nworld");
+ *
+ *
+ *
+ * Note that this is a convenience method that converts to the stored
+ * string literal token acceptable to setEscapedLiteral
.
+ *
+ *
+ * @param value the string value without enclosing double quotes and
+ * embedded escapes
+ * @exception IllegalArgumentException if the argument is incorrect
+ */
+ public void setLiteralValue(String value) {
+ if (value == null) {
+ throw new IllegalArgumentException();
+ }
+ int len = value.length();
+ StringBuffer b = new StringBuffer(len + 2);
+
+ b.append("\""); // opening delimiter //$NON-NLS-1$
+ for (int i = 0; i < len; i++) {
+ char c = value.charAt(i);
+ switch(c) {
+ case '\b' :
+ b.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ b.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ b.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ b.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ b.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\"':
+ b.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ b.append("\\\'"); //$NON-NLS-1$
+ break;
+ case '\\':
+ b.append("\\\\"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ b.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ b.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ b.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ b.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ b.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ b.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ b.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ b.append("\\7"); //$NON-NLS-1$
+ break;
+ default:
+ b.append(c);
+ }
+ }
+ b.append("\""); // closing delimiter //$NON-NLS-1$
+ setEscapedValue(b.toString());
+ }
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4 + stringSize(escapedValue);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/StructuralPropertyDescriptor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/StructuralPropertyDescriptor.java
new file mode 100644
index 0000000..ebfe7f8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/StructuralPropertyDescriptor.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Abstract base class for property descriptors of AST nodes.
+ * There are three kinds of properties:
+ *
+ * - simple properties ({@link SimplePropertyDescriptor})
+ * - properties where the value is a primitive (int, boolean)
+ * or simple (String, InfixExprsssion.Operator) type other than an
+ * AST node; for example, the identifier of a {@link SimpleName}
+ * - child properties ({@link ChildPropertyDescriptor})
+ * - properties whose value is another AST node;
+ * for example, the name of a {@link FunctionDeclaration}
+ * - child list properties ({@link ChildListPropertyDescriptor})
+ * - properties where the value is a list of AST nodes;
+ * for example, the statements of a {@link Block}
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class StructuralPropertyDescriptor {
+
+ /**
+ * Property id.
+ */
+ private final String propertyId;
+
+ /**
+ * The concrete AST node type that owns this property.
+ */
+ private final Class nodeClass;
+
+ /**
+ * Creates a new property descriptor for the given node type
+ * with the given property id.
+ * Note that this constructor is declared package-private so that
+ * property descriptors can only be created by the AST
+ * implementation.
+ *
+ * @param nodeClass concrete AST node type that owns this property
+ * @param propertyId the property id
+ */
+ StructuralPropertyDescriptor(Class nodeClass, String propertyId) {
+ if (nodeClass == null || propertyId == null) {
+ throw new IllegalArgumentException();
+ }
+ this.propertyId = propertyId;
+ this.nodeClass = nodeClass;
+ }
+
+ /**
+ * Returns the id of this property.
+ *
+ * @return the property id
+ */
+ public final String getId() {
+ return this.propertyId;
+ }
+
+ /**
+ * Returns the AST node type that owns this property.
+ *
+ * For example, for all properties of the node type
+ * TypeDeclaration, this method returns TypeDeclaration.class
.
+ *
+ *
+ * @return the node type that owns this property
+ */
+ public final Class getNodeClass() {
+ return this.nodeClass;
+ }
+
+ /**
+ * Returns whether this property is a simple property
+ * (instance of {@link SimplePropertyDescriptor}.
+ *
+ * @return true
if this is a simple property, and
+ * false
otherwise
+ */
+ public final boolean isSimpleProperty(){
+ return (this instanceof SimplePropertyDescriptor);
+ }
+
+ /**
+ * Returns whether this property is a child property
+ * (instance of {@link ChildPropertyDescriptor}.
+ *
+ * @return true
if this is a child property, and
+ * false
otherwise
+ */
+ public final boolean isChildProperty() {
+ return (this instanceof ChildPropertyDescriptor);
+ }
+
+ /**
+ * Returns whether this property is a child list property
+ * (instance of {@link ChildListPropertyDescriptor}.
+ *
+ * @return true
if this is a child list property, and
+ * false
otherwise
+ */
+ public final boolean isChildListProperty() {
+ return (this instanceof ChildListPropertyDescriptor);
+ }
+
+ /**
+ * Returns a string suitable for debug purposes.
+ * @return {@inheritDoc}
+ */
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ if (isChildListProperty()) {
+ b.append("ChildList"); //$NON-NLS-1$
+ }
+ if (isChildProperty()) {
+ b.append("Child"); //$NON-NLS-1$
+ }
+ if (isSimpleProperty()) {
+ b.append("Simple"); //$NON-NLS-1$
+ }
+ b.append("Property["); //$NON-NLS-1$
+ if (this.nodeClass != null) {
+ b.append(this.nodeClass.getName());
+ }
+ b.append(","); //$NON-NLS-1$
+ if (this.propertyId != null) {
+ b.append(this.propertyId);
+ }
+ b.append("]"); //$NON-NLS-1$
+ return b.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperConstructorInvocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperConstructorInvocation.java
new file mode 100644
index 0000000..a39583e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperConstructorInvocation.java
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Super constructor invocation statement AST node type.
+ * For JLS2: *
+ * SuperConstructorInvocation:
+ * [ Expression . ] super
+ * ( [ Expression { , Expression } ] ) ;
+ *
+ * For JLS3, type arguments are added:
+ *
+ * SuperConstructorInvocation:
+ * [ Expression . ]
+ * [ < Type { , Type } > ]
+ * super ( [ Expression { , Expression } ] ) ;
+ *
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public class SuperConstructorInvocation extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SuperConstructorInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperConstructorInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperConstructorInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SuperConstructorInvocation.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(SuperConstructorInvocation.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The expression; null
for none; defaults to none.
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * The type arguments (element type: Type
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for an super constructor invocation statement
+ * owned by the given AST. By default, no type arguments, and an empty list
+ * of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ SuperConstructorInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SUPER_CONSTRUCTOR_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SuperConstructorInvocation result = new SuperConstructorInvocation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this super constructor invocation statement,
+ * or null
if there is none.
+ *
+ * @return the expression node, or null
if there is none
+ */
+ public Expression getExpression() {
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets or clears the expression of this super constructor invocation
+ * statement.
+ *
+ * @param expression the expression node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this constructor
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: Type
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this super
+ * constructor invocation statement.
+ *
+ * @return the live list of argument expressions
+ * (element type: Expression
)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the constructor invoked by this
+ * expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the constructor binding, or null
if the binding
+ * cannot be resolved
+ */
+ public IFunctionBinding resolveConstructorBinding() {
+ return this.ast.getBindingResolver().resolveConstructor(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize()
+ + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperFieldAccess.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperFieldAccess.java
new file mode 100644
index 0000000..4fab26f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperFieldAccess.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "super" field access expression AST node type.
+ *
+ *
+ * SuperFieldAccess:
+ * [ ClassName . ] super . Identifier
+ *
+ *
+ *
+ * See FieldAccess
for guidelines on handling other expressions
+ * that resemble qualified names.
+ *
+ *
+ * @see FieldAccess
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public class SuperFieldAccess extends Expression {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(SuperFieldAccess.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SuperFieldAccess.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SuperFieldAccess.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; null
for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The field; lazily initialized; defaults to an unspecified,
+ * but legal, simple field name.
+ */
+ private SimpleName fieldName = null;
+
+ /**
+ * Creates a new unparented node for a super field access expression owned
+ * by the given AST. By default, field name is an unspecified, but legal,
+ * name, and there is no qualifier.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ SuperFieldAccess(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SUPER_FIELD_ACCESS;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SuperFieldAccess result = new SuperFieldAccess(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this "super" field access expression, or
+ * null
if there is none.
+ *
+ * @return the qualifier name node, or null
if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this "super" field access expression.
+ *
+ * @param name the qualifier name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name of the field accessed in this "super" field access
+ * expression.
+ *
+ * @return the field name
+ */
+ public SimpleName getName() {
+ if (this.fieldName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.fieldName == null) {
+ preLazyInit();
+ this.fieldName = new SimpleName(this.ast);
+ postLazyInit(this.fieldName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.fieldName;
+ }
+
+ /**
+ * Resolves and returns the binding for the field accessed by this
+ * expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the variable binding, or null
if the binding cannot
+ * be resolved
+ *
+ */
+ public IVariableBinding resolveFieldBinding() {
+ return this.ast.getBindingResolver().resolveField(this);
+ }
+
+ /**
+ * Sets the name of the field accessed in this "super" field access
+ * expression.
+ *
+ * @param fieldName the field name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName fieldName) {
+ if (fieldName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.fieldName;
+ preReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ this.fieldName = fieldName;
+ postReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.fieldName == null ? 0 : getName().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperMethodInvocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperMethodInvocation.java
new file mode 100644
index 0000000..6d7c31e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SuperMethodInvocation.java
@@ -0,0 +1,401 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "super" method invocation expression AST node type.
+ * For JLS2:
+ *
+ * SuperMethodInvocation:
+ * [ ClassName . ] super . Identifier
+ * ( [ Expression { , Expression } ] )
+ *
+ * For JLS3, type arguments are added:
+ *
+ * SuperMethodInvocation:
+ * [ ClassName . ] super .
+ * [ < Type { , Type } > ]
+ * Identifier ( [ Expression { , Expression } ] )
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SuperMethodInvocation extends Expression {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(SuperMethodInvocation.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "typeArguments" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperMethodInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(SuperMethodInvocation.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "arguments" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SuperMethodInvocation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(SuperMethodInvocation.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(5);
+ createPropertyList(SuperMethodInvocation.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(ARGUMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The optional qualifier; null
for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * The type arguments (element type: Type
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ */
+ private ASTNode.NodeList typeArguments = null;
+
+ /**
+ * The method name; lazily initialized; defaults to a unspecified,
+ * legal JavaScript method name.
+ */
+ private SimpleName methodName = null;
+
+ /**
+ * The list of argument expressions (element type:
+ * Expression
). Defaults to an empty list.
+ */
+ private ASTNode.NodeList arguments =
+ new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a "super" method invocation expression owned
+ * by the given AST. By default, no qualifier, no type arguments,
+ * an unspecified, but legal, method name, and an empty list of arguments.
+ *
+ * @param ast the AST that is to own this node
+ */
+ SuperMethodInvocation(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ARGUMENTS_PROPERTY) {
+ return arguments();
+ }
+ if (property == TYPE_ARGUMENTS_PROPERTY) {
+ return typeArguments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SUPER_METHOD_INVOCATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SuperMethodInvocation result = new SuperMethodInvocation(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((SimpleName) getName().clone(target));
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+ }
+ result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.typeArguments);
+ }
+ acceptChild(visitor, getName());
+ acceptChildren(visitor, this.arguments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this "super" method invocation expression, or
+ * null
if there is none.
+ *
+ * @return the qualifier name node, or null
if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this "super" method invocation expression.
+ *
+ * @param name the qualifier name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+
+ /**
+ * Returns true if the resolved return type has been inferred from the assignment context (JLS3 15.12.2.8), false otherwise.
+ *
+ * This information is available only when bindings are requested when the AST is being built
+ *
.
+ *
+ * @return true if the resolved return type has been inferred from the assignment context (JLS3 15.12.2.8), false otherwise
+ *
+ */
+ public boolean isResolvedTypeInferredFromExpectedType() {
+ return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
+ }
+
+ /**
+ * Returns the live ordered list of type arguments of this method
+ * invocation (added in JLS3 API).
+ *
+ * @return the live list of type arguments
+ * (element type: Type
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List typeArguments() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.typeArguments == null) {
+ unsupportedIn2();
+ }
+ return this.typeArguments;
+ }
+
+ /**
+ * Returns the name of the method invoked in this expression.
+ *
+ * @return the method name node
+ */
+ public SimpleName getName() {
+ if (this.methodName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.methodName == null) {
+ preLazyInit();
+ this.methodName = new SimpleName(this.ast);
+ postLazyInit(this.methodName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.methodName;
+ }
+
+ /**
+ * Sets the name of the method invoked in this expression to the
+ * given name.
+ *
+ * @param name the new method name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.methodName;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.methodName = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of argument expressions in this
+ * "super" method invocation expression.
+ *
+ * @return the live list of argument expressions
+ * (element type: Expression
)
+ */
+ public List arguments() {
+ return this.arguments;
+ }
+
+ /**
+ * Resolves and returns the binding for the method invoked by this
+ * expression.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the method binding, or null
if the binding cannot
+ * be resolved
+ *
+ */
+ public IFunctionBinding resolveMethodBinding() {
+ return this.ast.getBindingResolver().resolveMethod(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+ + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+ + (this.methodName == null ? 0 : getName().treeSize())
+ + (this.arguments == null ? 0 : this.arguments.listSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SwitchCase.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SwitchCase.java
new file mode 100644
index 0000000..ed758a9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SwitchCase.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Switch case AST node type. A switch case is a special kind of node used only
+ * in switch statements. It is a Statement
in name only.
+ *
+ *
+ * SwitchCase:
+ * case Expression :
+ * default :
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SwitchCase extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SwitchCase.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(SwitchCase.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; null
for none; lazily initialized (but
+ * does not default to none).
+ * @see #expressionInitialized
+ */
+ private Expression optionalExpression = null;
+
+ /**
+ * Indicates whether optionalExpression
has been initialized.
+ */
+ private boolean expressionInitialized = false;
+
+ /**
+ * Creates a new AST node for a switch case pseudo-statement owned by the
+ * given AST. By default, there is an unspecified, but legal, expression.
+ *
+ * @param ast the AST that is to own this node
+ */
+ SwitchCase(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SWITCH_CASE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SwitchCase result = new SwitchCase(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression(
+ (Expression) ASTNode.copySubtree(target, getExpression()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this switch case, or
+ * null
if there is none (the "default:" case).
+ *
+ * @return the expression node, or null
if there is none
+ */
+ public Expression getExpression() {
+ if (!this.expressionInitialized) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (!this.expressionInitialized) {
+ preLazyInit();
+ this.optionalExpression = new SimpleName(this.ast);
+ this.expressionInitialized = true;
+ postLazyInit(this.optionalExpression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.optionalExpression;
+ }
+
+ /**
+ * Sets the expression of this switch case, or clears it (turns it into
+ * the "default:" case).
+ *
+ * @param expression the expression node, or null
to
+ * turn it into the "default:" case
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ ASTNode oldChild = this.optionalExpression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.optionalExpression = expression;
+ this.expressionInitialized = true;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns whether this switch case represents the "default:" case.
+ *
+ * This convenience method is equivalent to
+ * getExpression() == null
.
+ *
+ *
+ * @return true
if this is the default switch case, and
+ * false
if this is a non-default switch case
+ */
+ public boolean isDefault() {
+ return getExpression() == null;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalExpression == null ? 0 : optionalExpression.treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SwitchStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SwitchStatement.java
new file mode 100644
index 0000000..c162410
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/SwitchStatement.java
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Switch statement AST node type.
+ *
+ *
+ * SwitchStatement:
+ * switch ( Expression )
+ * { { SwitchCase | Statement } } }
+ * SwitchCase:
+ * case Expression :
+ * default :
+ *
+ * SwitchCase
nodes are treated as a kind of
+ * Statement
.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SwitchStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(SwitchStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "statements" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(SwitchStatement.class, "statements", Statement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(SwitchStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(STATEMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The statements and SwitchCase nodes
+ * (element type: Statement
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList statements =
+ new ASTNode.NodeList(STATEMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented switch statement node owned by the given
+ * AST. By default, the swicth statement has an unspecified, but legal,
+ * expression, and an empty list of switch groups.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ SwitchStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == STATEMENTS_PROPERTY) {
+ return statements();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return SWITCH_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ SwitchStatement result = new SwitchStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.statements().addAll(ASTNode.copySubtrees(target, statements()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChildren(visitor, this.statements);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this switch statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this switch statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of statements for this switch statement.
+ * Within this list, SwitchCase
nodes mark the start of
+ * the switch groups.
+ *
+ * @return the live list of statement nodes
+ * (element type: Statement
)
+ */
+ public List statements() {
+ return this.statements;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + this.statements.listSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TagElement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TagElement.java
new file mode 100644
index 0000000..9eacf65
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TagElement.java
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a tag within a doc comment.
+ * Tag elements nested within another tag element are called
+ * inline doc tags.
+ *
+ * TagElement:
+ * [ @ Identifier ] { DocElement }
+ * DocElement:
+ * TextElement
+ * Name
+ * FunctionRef
+ * MemberRef
+ * { TagElement }
+ *
+ *
+ * @see JSdoc
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+*/
+public final class TagElement extends ASTNode implements IDocElement {
+
+ /**
+ * The "tagName" structural property of this node type.
+ *
+ *
+ */
+ public static final SimplePropertyDescriptor TAG_NAME_PROPERTY =
+ new SimplePropertyDescriptor(TagElement.class, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(TagElement.class, "fragments", IDocElement.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(TagElement.class, propertyList);
+ addProperty(TAG_NAME_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_AUTHOR = "@author"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ *
+ * Note that this tag first appeared in J2SE 5.
+ *
+ *
+ */
+ public static final String TAG_CODE = "@code"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_DEPRECATED = "@deprecated"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_DOCROOT = "@docRoot"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_EXCEPTION = "@exception"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_INHERITDOC = "@inheritDoc"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_LINK = "@link"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_LINKPLAIN = "@linkplain"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ *
+ * Note that this tag first appeared in J2SE 5.
+ *
+ *
+ */
+ public static final String TAG_LITERAL = "@literal"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_PARAM = "@param"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_RETURN = "@return"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SEE = "@see"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SERIAL = "@serial"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SERIALDATA= "@serialData"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SERIALFIELD= "@serialField"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_SINCE = "@since"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_THROWS = "@throws"; //$NON-NLS-1$
+
+ /**
+ * Standard inline doc tag name (value {@value}).
+ */
+ public static final String TAG_VALUE= "@value"; //$NON-NLS-1$
+
+ /**
+ * Standard doc tag name (value {@value}).
+ */
+ public static final String TAG_VERSION = "@version"; //$NON-NLS-1$
+
+ /**
+ * The tag name, or null if none; defaults to null.
+ */
+ private String optionalTagName = null;
+
+ /**
+ * The list of doc elements (element type: IDocElement
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList fragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new AST node for a tag element owned by the given AST.
+ * The new node has no name and an empty list of fragments.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ TagElement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == TAG_NAME_PROPERTY) {
+ if (get) {
+ return getTagName();
+ } else {
+ setTagName((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TAG_ELEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TagElement result = new TagElement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setTagName(getTagName());
+ result.fragments().addAll(ASTNode.copySubtrees(target, fragments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChildren(visitor, this.fragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns this node's tag name, or null
if none.
+ * For top level doc tags such as parameter tags, the tag name
+ * includes the "@" character ("@param").
+ * For inline doc tags such as link tags, the tag name
+ * includes the "@" character ("@link").
+ * The tag name may also be null
; this is used to
+ * represent the material at the start of a doc comment preceding
+ * the first explicit tag.
+ *
+ * @return the tag name, or null
if none
+ */
+ public String getTagName() {
+ return this.optionalTagName;
+ }
+
+ /**
+ * Sets the tag name of this node to the given value.
+ * For top level doc tags such as parameter tags, the tag name
+ * includes the "@" character ("@param").
+ * For inline doc tags such as link tags, the tag name
+ * includes the "@" character ("@link").
+ * The tag name may also be null
; this is used to
+ * represent the material at the start of a doc comment preceding
+ * the first explicit tag.
+ *
+ * @param tagName the tag name, or null
if none
+ */
+ public void setTagName(String tagName) {
+ preValueChange(TAG_NAME_PROPERTY);
+ this.optionalTagName = tagName;
+ postValueChange(TAG_NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of fragments in this tag element.
+ *
+ * The fragments cover everything following the tag name
+ * (or everything if there is no tag name), and generally omit
+ * embedded line breaks (and leading whitespace on new lines,
+ * including any leading "*"). {@link org.eclipse.wst.jsdt.core.dom.TagElement}
+ * nodes are used to represent tag elements (e.g., "@link")
+ * nested within this tag element.
+ *
+ *
+ * Here are some typical examples:
+ *
+ * - "@see Foo#bar()" - TagElement with tag name "@see";
+ * fragments() contains a single FunctionRef node
+ * - "@param args the program arguments" -
+ * TagElement with tag name "@param";
+ * 2 fragments: SimpleName ("args"), TextElement
+ * (" the program arguments")
+ * - "@return See {@link #foo foo} instead." -
+ * TagElement with tag name "@return";
+ * 3 fragments: TextElement ("See "),
+ * TagElement (for "@link #foo foo"),
+ * TextElement (" instead.")
+ *
+ * The use of Name, FunctionRef, and MemberRef nodes within
+ * tag elements allows these fragments to be queried for
+ * binding information.
+ *
+ *
+ * Adding and removing nodes from this list affects this node
+ * dynamically. The nodes in this list may be of various
+ * types, including {@link TextElement},
+ * {@link org.eclipse.wst.jsdt.core.dom.TagElement}, {@link Name},
+ * {@link MemberRef}, and {@link FunctionRef}.
+ * Clients should assume that the list of types may grow in
+ * the future, and write their code to deal with unexpected
+ * nodes types. However, attempts to add a non-proscribed type
+ * of node will trigger an exception.
+ *
+ * @return the live list of doc elements in this tag element
+ * (element type: ASTNode
)
+ */
+ public List fragments() {
+ return this.fragments;
+ }
+
+ /**
+ * Returns whether this tag element is nested within another
+ * tag element. Nested tag elements appears enclosed in
+ * "{" and "}"; certain doc tags, including "@link" and
+ * "@linkplain" are only meaningful as nested tags.
+ * Top-level (i.e., non-nested) doc tags begin on a new line;
+ * certain doc tags, including "@param" and
+ * "@see" are only meaningful as top-level tags.
+ *
+ * This convenience methods checks to see whether the parent
+ * of this node is of type {@link org.eclipse.wst.jsdt.core.dom.TagElement}.
+ *
+ *
+ * @return true
if this node is a nested tag element,
+ * and false if this node is either parented by a doc comment node
+ * ({@link JSdoc}), or is unparented
+ */
+ public boolean isNested() {
+ return (getParent() instanceof TagElement);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 2 * 4 + stringSize(this.optionalTagName);
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize() + this.fragments.listSize();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TextElement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TextElement.java
new file mode 100644
index 0000000..1133bf8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TextElement.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+/**
+ * AST node for a text element within a doc comment.
+ *
+ * TextElement:
+ * Sequence of characters not including a close comment delimiter */
+ *
+ *
+ * @see JSdoc
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class TextElement extends ASTNode implements IDocElement {
+
+ /**
+ * The "test" structural property of this node type.
+ *
+ *
+ */
+ public static final SimplePropertyDescriptor TEXT_PROPERTY =
+ new SimplePropertyDescriptor(TextElement.class, "text", String.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(TextElement.class, propertyList);
+ addProperty(TEXT_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The text element; defaults to the empty string.
+ */
+ private String text = Util.EMPTY_STRING;
+
+ /**
+ * Creates a new AST node for a text element owned by the given AST.
+ * The new node has an empty text string.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ TextElement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+ if (property == TEXT_PROPERTY) {
+ if (get) {
+ return getText();
+ } else {
+ setText((String) value);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetObjectProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TEXT_ELEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TextElement result = new TextElement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setText(getText());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns this node's text.
+ *
+ * @return the text of this node
+ */
+ public String getText() {
+ return this.text;
+ }
+
+ /**
+ * Sets the text of this node to the given value.
+ *
+ * The text element typically includes leading and trailing
+ * whitespace that separates it from the immediately preceding
+ * or following elements. The text element must not include
+ * a block comment closing delimiter "*"+"/".
+ *
+ *
+ * @param text the text of this node
+ * @exception IllegalArgumentException if the text is null
+ * or contains a block comment closing delimiter
+ */
+ public void setText(String text) {
+ if (text == null) {
+ throw new IllegalArgumentException();
+ }
+ if (text.indexOf("*/") > 0) { //$NON-NLS-1$
+ throw new IllegalArgumentException();
+ }
+ preValueChange(TEXT_PROPERTY);
+ this.text = text;
+ postValueChange(TEXT_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ int size = BASE_NODE_SIZE + 1 * 4;
+ if (this.text != Util.EMPTY_STRING) {
+ // everything but our empty string costs
+ size += stringSize(this.text);
+ }
+ return size;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ThisExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ThisExpression.java
new file mode 100644
index 0000000..0d691e5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ThisExpression.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "this" AST node type.
+ *
+ *
+ * ThisExpression:
+ * [ ClassName . ] this
+ *
+ *
+ * See FieldAccess
for guidelines on handling other expressions
+ * that resemble qualified names.
+ *
+ *
+ * @see FieldAccess
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ThisExpression extends Expression {
+
+ /**
+ * The "qualifier" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(ThisExpression.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ThisExpression.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The optional qualifier; null
for none; defaults to none.
+ */
+ private Name optionalQualifier = null;
+
+ /**
+ * Creates a new AST node for a "this" expression owned by the
+ * given AST. By default, there is no qualifier.
+ *
+ * @param ast the AST that is to own this node
+ */
+ ThisExpression(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return THIS_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ThisExpression result = new ThisExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getQualifier());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this "this" expression, or
+ * null
if there is none.
+ *
+ * @return the qualifier name node, or null
if there is none
+ */
+ public Name getQualifier() {
+ return this.optionalQualifier;
+ }
+
+ /**
+ * Sets or clears the qualifier of this "this" expression.
+ *
+ * @param name the qualifier name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setQualifier(Name name) {
+ ASTNode oldChild = this.optionalQualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.optionalQualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.optionalQualifier == null ? 0 : getQualifier().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ThrowStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ThrowStatement.java
new file mode 100644
index 0000000..361d246
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/ThrowStatement.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Throw statement AST node type.
+ *
+ *
+ * ThrowStatement:
+ * throw Expression ;
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ThrowStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(ThrowStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(ThrowStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to a unspecified, but legal,
+ * expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * Creates a new unparented throw statement node owned by the given
+ * AST. By default, the throw statement has an unspecified, but legal,
+ * expression.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ ThrowStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return THROW_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ ThrowStatement result = new ThrowStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getExpression());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this throw statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this throw statement.
+ *
+ * @param expression the new expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TryStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TryStatement.java
new file mode 100644
index 0000000..c37496a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TryStatement.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Try statement AST node type.
+ *
+ *
+ * TryStatement:
+ * try Block
+ * { CatchClause }
+ * [ finally Block ]
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TryStatement extends Statement {
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(TryStatement.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "catchClauses" structural property of this node type.
+ *
+ */
+ public static final ChildListPropertyDescriptor CATCH_CLAUSES_PROPERTY =
+ new ChildListPropertyDescriptor(TryStatement.class, "catchClauses", CatchClause.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "finally" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor FINALLY_PROPERTY =
+ new ChildPropertyDescriptor(TryStatement.class, "finally", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(TryStatement.class, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
+ addProperty(FINALLY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The body; lazily initialized; defaults to an empty block.
+ */
+ private Block body = null;
+
+ /**
+ * The catch clauses (element type: CatchClause
).
+ * Defaults to an empty list.
+ */
+ private ASTNode.NodeList catchClauses =
+ new ASTNode.NodeList(CATCH_CLAUSES_PROPERTY);
+
+ /**
+ * The finally block, or null
if none.
+ * Defaults to none.
+ */
+ private Block optionalFinallyBody = null;
+
+
+ /**
+ * Creates a new AST node for a try statement owned by the given
+ * AST. By default, the try statement has an empty block, no catch
+ * clauses, and no finally block.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ TryStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Block) child);
+ return null;
+ }
+ }
+ if (property == FINALLY_PROPERTY) {
+ if (get) {
+ return getFinally();
+ } else {
+ setFinally((Block) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == CATCH_CLAUSES_PROPERTY) {
+ return catchClauses();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TRY_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TryStatement result = new TryStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setBody((Block) getBody().clone(target));
+ result.catchClauses().addAll(
+ ASTNode.copySubtrees(target, catchClauses()));
+ result.setFinally(
+ (Block) ASTNode.copySubtree(target, getFinally()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getBody());
+ acceptChildren(visitor, this.catchClauses);
+ acceptChild(visitor, getFinally());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the body of this try statement.
+ *
+ * @return the try body
+ */
+ public Block getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this try statement.
+ *
+ * @param body the block node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Block body) {
+ if (body == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, body, BODY_PROPERTY);
+ this.body = body;
+ postReplaceChild(oldChild, body, BODY_PROPERTY);
+ }
+
+ /**
+ * Returns the live ordered list of catch clauses for this try statement.
+ *
+ * @return the live list of catch clauses
+ * (element type: CatchClause
)
+ */
+ public List catchClauses() {
+ return this.catchClauses;
+ }
+
+ /**
+ * Returns the finally block of this try statement, or null
if
+ * this try statement has no finally block.
+ *
+ * @return the finally block, or null
if this try statement
+ * has none
+ */
+ public Block getFinally() {
+ return this.optionalFinallyBody;
+ }
+
+ /**
+ * Sets or clears the finally block of this try statement.
+ *
+ * @param block the finally block node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setFinally(Block block) {
+ ASTNode oldChild = this.optionalFinallyBody;
+ preReplaceChild(oldChild, block, FINALLY_PROPERTY);
+ this.optionalFinallyBody = block;
+ postReplaceChild(oldChild, block, FINALLY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.body == null ? 0 : getBody().treeSize())
+ + this.catchClauses.listSize()
+ + (this.optionalFinallyBody == null ? 0 : getFinally().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Type.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Type.java
new file mode 100644
index 0000000..449d17a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/Type.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Abstract base class of all type AST node types. A type node represents a
+ * reference to a primitive type (including void), to an array type, or to a
+ * simple named type (or type variable), to a qualified type, or to a
+ * parameterized type. Note that not all of these
+ * are meaningful in all contexts.
+ *
+ *
+ * Type:
+ * PrimitiveType
+ * ArrayType
+ * SimpleType
+ * QualifiedType
+ * ParameterizedType
+ * PrimitiveType:
+ * byte
+ * short
+ * char
+ * int
+ * long
+ * float
+ * double
+ * boolean
+ * void
+ * ArrayType:
+ * Type [ ]
+ * SimpleType:
+ * TypeName
+ * QualifiedType:
+ * Type . SimpleName
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class Type extends ASTNode {
+
+ /**
+ * Creates a new AST node for a type owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ Type(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns whether this type is a primitive type
+ * (PrimitiveType
).
+ *
+ * @return true
if this is a primitive type, and
+ * false
otherwise
+ */
+ public final boolean isPrimitiveType() {
+ return (this instanceof PrimitiveType);
+ }
+
+ /**
+ * Returns whether this type is a simple type
+ * (SimpleType
).
+ *
+ * @return true
if this is a simple type, and
+ * false
otherwise
+ */
+ public final boolean isSimpleType() {
+ return (this instanceof SimpleType);
+ }
+
+ /**
+ * Returns whether this type is an array type
+ * (ArrayType
).
+ *
+ * @return true
if this is an array type, and
+ * false
otherwise
+ */
+ public final boolean isArrayType() {
+ return (this instanceof ArrayType);
+ }
+
+ /**
+ * Returns whether this type is a qualified type
+ * (QualifiedType
).
+ *
+ * Note that a type like "A.B" can be represented either of two ways:
+ *
+ * -
+ *
QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))
+ *
+ * -
+ *
SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))
+ *
+ *
+ * The first form is preferred when "A" is known to be a type. However, a
+ * parser cannot always determine this. Clients should be prepared to handle
+ * either rather than make assumptions. (Note also that the first form
+ * became possible as of JLS3; only the second form existed in the
+ * JLS2 API.)
+ *
+ *
+ * @return true
if this is a qualified type, and
+ * false
otherwise
+ *
+ */
+ public final boolean isQualifiedType() {
+ return (this instanceof QualifiedType);
+ }
+
+ /**
+ * Resolves and returns the binding for this type.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the type binding, or null
if the binding cannot be
+ * resolved
+ */
+ public final ITypeBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ public boolean isInferred()
+ {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeBinding.java
new file mode 100644
index 0000000..4480c42
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeBinding.java
@@ -0,0 +1,824 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.jsdt.core.IClassFile;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.IPackageFragment;
+import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.env.IDependent;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+import org.eclipse.wst.jsdt.internal.core.ClassFile;
+import org.eclipse.wst.jsdt.internal.core.JavaElement;
+
+/**
+ * Internal implementation of type bindings.
+ */
+class TypeBinding implements ITypeBinding {
+ protected static final IFunctionBinding[] NO_METHOD_BINDINGS = new IFunctionBinding[0];
+
+ private static final String NO_NAME = ""; //$NON-NLS-1$
+ protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+ protected static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
+
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding;
+ private String key;
+ private BindingResolver resolver;
+ private IVariableBinding[] fields;
+ private IFunctionBinding[] methods;
+ private ITypeBinding[] members;
+
+ public TypeBinding(BindingResolver resolver, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding binding) {
+ this.binding = binding;
+ this.resolver = resolver;
+ }
+
+ public ITypeBinding createArrayType(int dimension) {
+ int realDimensions = dimension;
+ realDimensions += this.getDimensions();
+ if (realDimensions < 1 || realDimensions > 255) {
+ throw new IllegalArgumentException();
+ }
+ return this.resolver.resolveArrayType(this, dimension);
+ }
+
+
+ /*
+ * @see ITypeBinding#getBinaryName()
+ *
+ */
+ public String getBinaryName() {
+ char[] constantPoolName = this.binding.constantPoolName();
+ if (constantPoolName == null) return null;
+ char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
+ return new String(dotSeparated);
+ }
+
+ /*
+ * Returns the class file for the given file name, or null if not found.
+ * @see org.eclipse.wst.jsdt.internal.compiler.env.IDependent#getFileName()
+ */
+ private IClassFile getClassFile(char[] fileName) {
+ int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+ int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
+ if (pkgEnd == -1)
+ pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
+ if (jarSeparator != -1 && pkgEnd < jarSeparator) // if in a jar and no slash, it is a default package -> pkgEnd should be equal to jarSeparator
+ pkgEnd = jarSeparator;
+ if (pkgEnd == -1)
+ return null;
+ IPackageFragment pkg = getPackageFragment(fileName, pkgEnd, jarSeparator);
+ if (pkg == null) return null;
+ int start;
+ return pkg.getClassFile(new String(fileName, start = pkgEnd + 1, fileName.length - start));
+ }
+
+ /*
+ * Returns the javaScript unit for the given file name, or null if not found.
+ * @see org.eclipse.wst.jsdt.internal.compiler.env.IDependent#getFileName()
+ */
+ private IJavaScriptUnit getCompilationUnit(char[] fileName) {
+ char[] slashSeparatedFileName = CharOperation.replaceOnCopy(fileName, File.separatorChar, '/');
+ int pkgEnd = CharOperation.lastIndexOf('/', slashSeparatedFileName); // pkgEnd is exclusive
+ if (pkgEnd == -1)
+ return null;
+ IPackageFragment pkg = getPackageFragment(slashSeparatedFileName, pkgEnd, -1/*no jar separator for .js files*/);
+ if (pkg == null) return null;
+ int start;
+ IJavaScriptUnit cu = pkg.getJavaScriptUnit(new String(slashSeparatedFileName, start = pkgEnd+1, slashSeparatedFileName.length - start));
+ if (this.resolver instanceof DefaultBindingResolver) {
+ IJavaScriptUnit workingCopy = cu.findWorkingCopy(((DefaultBindingResolver) this.resolver).workingCopyOwner);
+ if (workingCopy != null)
+ return workingCopy;
+ }
+ return cu;
+ }
+
+ /*
+ * @see ITypeBinding#getComponentType()
+ */
+ public ITypeBinding getComponentType() {
+ if (!this.isArray()) {
+ return null;
+ }
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return resolver.getTypeBinding(arrayBinding.elementsType());
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredFields()
+ */
+ public synchronized IVariableBinding[] getDeclaredFields() {
+ if (this.fields != null) {
+ return this.fields;
+ }
+ try {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ FieldBinding[] fieldBindings = referenceBinding.availableFields(); // resilience
+ int length = fieldBindings.length;
+ if (length != 0) {
+ IVariableBinding[] newFields = new IVariableBinding[length];
+ for (int i = 0; i < length; i++) {
+ IVariableBinding variableBinding = this.resolver.getVariableBinding(fieldBindings[i]);
+ if (variableBinding == null) {
+ return this.fields = NO_VARIABLE_BINDINGS;
+ }
+ newFields[i] = variableBinding;
+ }
+ return this.fields = newFields;
+ }
+ }
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "Could not retrieve declared fields"); //$NON-NLS-1$
+ }
+ return this.fields = NO_VARIABLE_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredMethods()
+ */
+ public synchronized IFunctionBinding[] getDeclaredMethods() {
+ if (this.methods != null) {
+ return this.methods;
+ }
+ try {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient
+ int length = internalMethods.length;
+ if (length != 0) {
+ int removeSyntheticsCounter = 0;
+ IFunctionBinding[] newMethods = new IFunctionBinding[length];
+ for (int i = 0; i < length; i++) {
+ org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding = internalMethods[i];
+ if (!shouldBeRemoved(methodBinding)) {
+ IFunctionBinding methodBinding2 = this.resolver.getMethodBinding(methodBinding);
+ if (methodBinding2 != null) {
+ newMethods[removeSyntheticsCounter++] = methodBinding2;
+ }
+ }
+ }
+ if (removeSyntheticsCounter != length) {
+ System.arraycopy(newMethods, 0, (newMethods = new IFunctionBinding[removeSyntheticsCounter]), 0, removeSyntheticsCounter);
+ }
+ return this.methods = newMethods;
+ }
+ }
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
+ }
+ return this.methods = NO_METHOD_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredModifiers()
+ */
+ public int getDeclaredModifiers() {
+ return getModifiers();
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaredTypes()
+ */
+ public synchronized ITypeBinding[] getDeclaredTypes() {
+ if (this.members != null) {
+ return this.members;
+ }
+ try {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ ReferenceBinding[] internalMembers = referenceBinding.memberTypes();
+ int length = internalMembers.length;
+ if (length != 0) {
+ ITypeBinding[] newMembers = new ITypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ ITypeBinding typeBinding = this.resolver.getTypeBinding(internalMembers[i]);
+ if (typeBinding == null) {
+ return this.members = NO_TYPE_BINDINGS;
+ }
+ newMembers[i] = typeBinding;
+ }
+ return this.members = newMembers;
+ }
+ }
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
+ }
+ return this.members = NO_TYPE_BINDINGS;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaringMethod()
+ */
+ public synchronized IFunctionBinding getDeclaringMethod() {
+ if (this.binding instanceof LocalTypeBinding) {
+ LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.binding;
+ MethodBinding methodBinding = localTypeBinding.enclosingMethod;
+ if (methodBinding != null) {
+ try {
+ return this.resolver.getMethodBinding(localTypeBinding.enclosingMethod);
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDeclaringClass()
+ */
+ public synchronized ITypeBinding getDeclaringClass() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ if (referenceBinding.isNestedType()) {
+ try {
+ return this.resolver.getTypeBinding(referenceBinding.enclosingType());
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see ITypeBinding#getDimensions()
+ */
+ public int getDimensions() {
+ if (!this.isArray()) {
+ return 0;
+ }
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return arrayBinding.dimensions;
+ }
+
+ /*
+ * @see ITypeBinding#getElementType()
+ */
+ public ITypeBinding getElementType() {
+ if (!this.isArray()) {
+ return null;
+ }
+ ArrayBinding arrayBinding = (ArrayBinding) binding;
+ return resolver.getTypeBinding(arrayBinding.leafComponentType);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getTypeDeclaration()
+ */
+ public ITypeBinding getTypeDeclaration() {
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getErasure()
+ */
+ public ITypeBinding getErasure() {
+ return this.resolver.getTypeBinding(this.binding);
+ }
+
+ public IJavaScriptElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element == null)
+ return null;
+ return element.resolved(this.binding);
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ return getUnresolvedJavaElement(this.binding);
+ }
+ private JavaElement getUnresolvedJavaElement(org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding typeBinding ) {
+ if (typeBinding == null)
+ return null;
+ switch (typeBinding.kind()) {
+ case Binding.ARRAY_TYPE :
+ typeBinding = ((ArrayBinding) typeBinding).leafComponentType();
+ return getUnresolvedJavaElement(typeBinding);
+ case Binding.BASE_TYPE :
+ return null;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+ char[] fileName = referenceBinding.getFileName();
+ if (referenceBinding.isLocalType() || referenceBinding.isAnonymousType()) {
+ // local or anonymous type
+ if (Util.isClassFileName(fileName)) {
+ int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
+ int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
+ if (pkgEnd == -1)
+ pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
+ if (jarSeparator != -1 && pkgEnd < jarSeparator) // if in a jar and no slash, it is a default package -> pkgEnd should be equal to jarSeparator
+ pkgEnd = jarSeparator;
+ if (pkgEnd == -1)
+ return null;
+ IPackageFragment pkg = getPackageFragment(fileName, pkgEnd, jarSeparator);
+ char[] constantPoolName = referenceBinding.constantPoolName();
+ if (constantPoolName == null) {
+ ClassFile classFile = (ClassFile) getClassFile(fileName);
+ return classFile == null ? null : (JavaElement) classFile.getType();
+ }
+ pkgEnd = CharOperation.lastIndexOf('/', constantPoolName);
+ char[] classFileName = CharOperation.subarray(constantPoolName, pkgEnd+1, constantPoolName.length);
+ ClassFile classFile = (ClassFile) pkg.getClassFile(new String(classFileName) + SuffixConstants.SUFFIX_STRING_java);
+ return (JavaElement) classFile.getType();
+ }
+ IJavaScriptUnit cu = getCompilationUnit(fileName);
+ if (cu == null) return null;
+ // must use getElementAt(...) as there is no back pointer to the defining method (scope is null after resolution has ended)
+ try {
+ int sourceStart = ((LocalTypeBinding) referenceBinding).sourceStart;
+ return (JavaElement) cu.getElementAt(sourceStart);
+ } catch (JavaScriptModelException e) {
+ // does not exist
+ return null;
+ }
+ } else {
+ if (fileName == null) return null; // case of a WilCardBinding that doesn't have a corresponding JavaScript element
+ // member or top level type
+ ITypeBinding declaringTypeBinding = null;
+ if (this.isArray()) {
+ declaringTypeBinding = this.getElementType().getDeclaringClass();
+ } else {
+ declaringTypeBinding = this.getDeclaringClass();
+ }
+ if (declaringTypeBinding == null) {
+ // top level type
+ if (Util.isClassFileName(fileName)) {
+ ClassFile classFile = (ClassFile) getClassFile(fileName);
+ if (classFile == null) return null;
+ return (JavaElement) classFile.getType();
+ }
+ IJavaScriptUnit cu = getCompilationUnit(fileName);
+ if (cu == null) return null;
+ return (JavaElement) cu.getType(new String(referenceBinding.sourceName()));
+ } else {
+ // member type
+ IType declaringType = (IType) declaringTypeBinding.getJavaElement();
+ if (declaringType == null) return null;
+ return (JavaElement) declaringType.getType(new String(referenceBinding.sourceName()));
+ }
+ }
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.TYPE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+ if (referenceBinding.isAnonymousType()) {
+ return accessFlags & ~Modifier.FINAL;
+ }
+ return accessFlags;
+ } else {
+ return Modifier.NONE;
+ }
+ }
+
+ public String getName() {
+ StringBuffer buffer;
+ switch (this.binding.kind()) {
+
+ case Binding.ARRAY_TYPE :
+ ITypeBinding elementType = getElementType();
+ if (elementType.isLocal() || elementType.isAnonymous()) {
+ return NO_NAME;
+ }
+ int dimensions = getDimensions();
+ char[] brackets = new char[dimensions * 2];
+ for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ buffer = new StringBuffer(elementType.getName());
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+
+ default :
+ if (isPrimitive() || isNullType()) {
+ BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+ return new String(baseTypeBinding.simpleName);
+ }
+ if (isAnonymous()) {
+ return NO_NAME;
+ }
+ return new String(this.binding.sourceName());
+ }
+ }
+
+ /*
+ * @see ITypeBinding#getPackage()
+ */
+ public IPackageBinding getPackage() {
+ switch (this.binding.kind()) {
+ case Binding.BASE_TYPE :
+ case Binding.ARRAY_TYPE :
+ return null;
+ }
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return this.resolver.getPackageBinding(referenceBinding.getPackage());
+ }
+
+ /*
+ * Returns the package that includes the given file name, or null if not found.
+ * pkgEnd == jarSeparator if default package in a jar
+ * pkgEnd > jarSeparator if non default package in a jar
+ * pkgEnd > 0 if package not in a jar
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.env.IDependent#getFileName()
+ */
+ private IPackageFragment getPackageFragment(char[] fileName, int pkgEnd, int jarSeparator) {
+ if (jarSeparator != -1) {
+ String jarMemento = new String(fileName, 0, jarSeparator);
+ IPackageFragmentRoot root = (IPackageFragmentRoot) JavaScriptCore.create(jarMemento);
+ if (pkgEnd == jarSeparator)
+ return root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ char[] pkgName = CharOperation.subarray(fileName, jarSeparator+1, pkgEnd);
+ CharOperation.replace(pkgName, '/', '.');
+ return root.getPackageFragment(new String(pkgName));
+ } else {
+ Path path = new Path(new String(fileName, 0, pkgEnd));
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IContainer folder = path.segmentCount() == 1 ? workspaceRoot.getProject(path.lastSegment()) : (IContainer) workspaceRoot.getFolder(path);
+ IJavaScriptElement element = JavaScriptCore.create(folder);
+ if (element == null) return null;
+ switch (element.getElementType()) {
+ case IJavaScriptElement.PACKAGE_FRAGMENT:
+ return (IPackageFragment) element;
+ case IJavaScriptElement.PACKAGE_FRAGMENT_ROOT:
+ return ((IPackageFragmentRoot) element).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ case IJavaScriptElement.JAVASCRIPT_PROJECT:
+ IPackageFragmentRoot root = ((IJavaScriptProject) element).getPackageFragmentRoot(folder);
+ if (root == null) return null;
+ return root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.core.dom.ITypeBinding#getQualifiedName()
+ */
+ public String getQualifiedName() {
+ StringBuffer buffer;
+ switch (this.binding.kind()) {
+
+ case Binding.ARRAY_TYPE :
+ ITypeBinding elementType = getElementType();
+ if (elementType.isLocal() || elementType.isAnonymous()) {
+ return NO_NAME;
+ }
+ final int dimensions = getDimensions();
+ char[] brackets = new char[dimensions * 2];
+ for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+ brackets[i] = ']';
+ brackets[i - 1] = '[';
+ }
+ buffer = new StringBuffer(elementType.getQualifiedName());
+ buffer.append(brackets);
+ return String.valueOf(buffer);
+
+ default :
+ if (isAnonymous() || isLocal()) {
+ return NO_NAME;
+ }
+ if (isPrimitive() || isNullType()) {
+ BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+ return new String(baseTypeBinding.simpleName);
+ }
+ if (isMember()) {
+ buffer = new StringBuffer();
+ buffer
+ .append(getDeclaringClass().getQualifiedName())
+ .append('.');
+ buffer.append(getName());
+ return String.valueOf(buffer);
+ }
+ PackageBinding packageBinding = this.binding.getPackage();
+ buffer = new StringBuffer();
+ if (packageBinding != null && packageBinding.compoundName != CharOperation.NO_CHAR_CHAR) {
+ buffer.append(CharOperation.concatWith(packageBinding.compoundName, '.')).append('.');
+ }
+ buffer.append(getName());
+ return String.valueOf(buffer);
+ }
+ }
+
+ /*
+ * @see ITypeBinding#getSuperclass()
+ */
+ public synchronized ITypeBinding getSuperclass() {
+ if (this.binding == null)
+ return null;
+ switch (this.binding.kind()) {
+ case Binding.ARRAY_TYPE :
+ case Binding.BASE_TYPE :
+ return null;
+ }
+ ReferenceBinding superclass = null;
+ try {
+ superclass = ((ReferenceBinding)this.binding).superclass();
+ } catch (RuntimeException e) {
+ /* in case a method cannot be resolvable due to missing jars on the includepath
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+ */
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "Could not retrieve superclass"); //$NON-NLS-1$
+ return this.resolver.resolveWellKnownType("Object"); //$NON-NLS-1$
+ }
+ if (superclass == null) {
+ return null;
+ }
+ return this.resolver.getTypeBinding(superclass);
+ }
+
+ /*
+ * @see ITypeBinding#isAnonymous()
+ */
+ public boolean isAnonymous() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isAnonymousType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isArray()
+ */
+ public boolean isArray() {
+ return binding.isArrayType();
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
+ */
+ public boolean isAssignmentCompatible(ITypeBinding type) {
+ try {
+ if (this == type) return true;
+ if (!(type instanceof TypeBinding)) return false;
+ TypeBinding other = (TypeBinding) type;
+ Scope scope = this.resolver.scope();
+ if (scope == null) return false;
+ return this.binding.isCompatibleWith(other.binding) || scope.isBoxingCompatibleWith(this.binding, other.binding);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isCastCompatible(ITypeBinding)
+ */
+ public boolean isCastCompatible(ITypeBinding type) {
+ try {
+ Expression expression = new Expression() {
+ public StringBuffer printExpression(int indent,StringBuffer output) {
+ return null;
+ }
+ };
+ Scope scope = this.resolver.scope();
+ if (scope == null) return false;
+ if (!(type instanceof TypeBinding)) return false;
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding expressionType = ((TypeBinding) type).binding;
+ // simulate capture in case checked binding did not properly get extracted from a reference
+ return expression.checkCastTypesCompatibility(scope, this.binding, expressionType, null);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /*
+ * @see ITypeBinding#isClass()
+ */
+ public boolean isClass() {
+ return this.binding.isClass();
+ }
+
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isDeprecated();
+ }
+ return false;
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ *
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof TypeBinding)) {
+ return false;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding;
+ // check return type
+ return BindingComparator.isEqual(this.binding, otherBinding);
+ }
+
+ /*
+ * @see ITypeBinding#isFromSource()
+ */
+ public boolean isFromSource() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return !referenceBinding.isBinaryBinding();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isLocal()
+ */
+ public boolean isLocal() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isLocalType() && !referenceBinding.isMemberType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isMember()
+ */
+ public boolean isMember() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isMemberType();
+ }
+ return false;
+ }
+
+ /*
+ * @see ITypeBinding#isNested()
+ */
+ public boolean isNested() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return referenceBinding.isNestedType();
+ }
+ return false;
+ }
+
+ /**
+ * @see ITypeBinding#isNullType()
+ */
+ public boolean isNullType() {
+ return this.binding == org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding.NULL;
+ }
+
+ /*
+ * @see ITypeBinding#isPrimitive()
+ */
+ public boolean isPrimitive() {
+ return !isNullType() && binding.isBaseType();
+ }
+
+ /* (non-Javadoc)
+ * @see IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see ITypeBinding#isSubTypeCompatible(ITypeBinding)
+ */
+ public boolean isSubTypeCompatible(ITypeBinding type) {
+ try {
+ if (this == type) return true;
+ if (this.binding.isBaseType()) return false;
+ if (!(type instanceof TypeBinding)) return false;
+ TypeBinding other = (TypeBinding) type;
+ if (other.binding.isBaseType()) return false;
+ return this.binding.isCompatibleWith(other.binding);
+ } catch (AbortCompilation e) {
+ // don't surface internal exception to clients
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+ return false;
+ }
+ }
+
+ /*
+ * @see ITypeBinding#isTopLevel()
+ */
+ public boolean isTopLevel() {
+ if (isClass()) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+ return !referenceBinding.isNestedType();
+ }
+ return false;
+ }
+
+ private boolean shouldBeRemoved(org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding methodBinding) {
+ return methodBinding.isDefaultAbstract();
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+
+ public boolean isCompilationUnit()
+ {
+ return false;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeDeclaration.java
new file mode 100644
index 0000000..3698683
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeDeclaration.java
@@ -0,0 +1,635 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Type declaration AST node type. A type declaration
+ * is the union of a class declaration and an interface declaration.
+ * For JLS2:
+ *
+ * TypeDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * ClassDeclaration:
+ * [ jsdoc ] { Modifier } class Identifier
+ * [ extends Type]
+ * [ implements Type { , Type } ]
+ * { { ClassBodyDeclaration | ; } }
+ * InterfaceDeclaration:
+ * [ jsdoc ] { Modifier } interface Identifier
+ * [ extends Type { , Type } ]
+ * { { InterfaceBodyDeclaration | ; } }
+ *
+ * For JLS3, type parameters and reified modifiers
+ * (and annotations) were added, and the superclass type name and superinterface
+ * types names are generalized to type so that parameterized types can be
+ * referenced:
+ *
+ * TypeDeclaration:
+ * ClassDeclaration
+ * InterfaceDeclaration
+ * ClassDeclaration:
+ * [ jsdoc ] { ExtendedModifier } class Identifier
+ * [ < TypeParameter { , TypeParameter } > ]
+ * [ extends Type ]
+ * [ implements Type { , Type } ]
+ * { { ClassBodyDeclaration | ; } }
+ * InterfaceDeclaration:
+ * [ jsdoc ] { ExtendedModifier } interface Identifier
+ * [ < TypeParameter { , TypeParameter } > ]
+ * [ extends Type { , Type } ]
+ * { { InterfaceBodyDeclaration | ; } }
+ *
+ *
+ * When a jsdoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no jsdoc comment, the source range begins with the first
+ * character of the first modifier or annotation (if any), or the
+ * first character of the "class" or "interface" keyword (if no
+ * modifiers or annotations). The source range extends through the last character of the "}"
+ * token following the body declarations.
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TypeDeclaration extends AbstractTypeDeclaration {
+
+ /**
+ * The "javadoc" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ internalJavadocPropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ internalModifiersPropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ internalModifiers2PropertyFactory(TypeDeclaration.class);
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ internalNamePropertyFactory(TypeDeclaration.class);
+
+
+ /**
+ * The "superclass" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final ChildPropertyDescriptor SUPERCLASS_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclaration.class, "superclass", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "superclassType" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildPropertyDescriptor SUPERCLASS_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclaration.class, "superclassType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "bodyDeclarations" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY =
+ internalBodyDeclarationPropertyFactory(TypeDeclaration.class);
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(8);
+ createPropertyList(TypeDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(SUPERCLASS_PROPERTY, propertyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(9);
+ createPropertyList(TypeDeclaration.class, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(SUPERCLASS_TYPE_PROPERTY, propertyList);
+ addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The optional superclass name; null
if none.
+ * Defaults to none. Note that this field is not used for
+ * interface declarations. Not used in 3.0.
+ */
+ private Name optionalSuperclassName = null;
+
+ /**
+ * The optional superclass type; null
if none.
+ * Defaults to none. Note that this field is not used for
+ * interface declarations. Null in JLS2. Added in JLS3.
+ *
+ */
+ private Type optionalSuperclassType = null;
+
+ /**
+ * Creates a new AST node for a type declaration owned by the given
+ * AST. By default, the type declaration is for a class of an
+ * unspecified, but legal, name; no modifiers; no javadoc;
+ * no type parameters; no superclass or superinterfaces; and an empty list
+ * of body declarations.
+ *
+ * N.B. This constructor is package-private; all subclasses must be
+ * declared in the same package; clients are unable to declare
+ * additional subclasses.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ internalSetModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+ // allow default implementation to flag the error
+ return super.internalGetSetBooleanProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((JSdoc) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == SUPERCLASS_PROPERTY) {
+ if (get) {
+ return getSuperclass();
+ } else {
+ setSuperclass((Name) child);
+ return null;
+ }
+ }
+ if (property == SUPERCLASS_TYPE_PROPERTY) {
+ if (get) {
+ return getSuperclassType();
+ } else {
+ setSuperclassType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == BODY_DECLARATIONS_PROPERTY) {
+ return bodyDeclarations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final ChildListPropertyDescriptor internalModifiers2Property() {
+ return MODIFIERS2_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on BodyDeclaration.
+ */
+ final SimplePropertyDescriptor internalModifiersProperty() {
+ return MODIFIERS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AbstractTypeDeclaration.
+ */
+ final ChildListPropertyDescriptor internalBodyDeclarationsProperty() {
+ return BODY_DECLARATIONS_PROPERTY;
+ }
+
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TYPE_DECLARATION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TypeDeclaration result = new TypeDeclaration(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setJavadoc(
+ (JSdoc) ASTNode.copySubtree(target, getJavadoc()));
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.internalSetModifiers(getModifiers());
+ result.setSuperclass(
+ (Name) ASTNode.copySubtree(target, getSuperclass()));
+ }
+ result.setName((SimpleName) getName().clone(target));
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ result.setSuperclassType(
+ (Type) ASTNode.copySubtree(target, getSuperclassType()));
+ }
+ result.bodyDeclarations().addAll(
+ ASTNode.copySubtrees(target, bodyDeclarations()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ acceptChild(visitor, getJavadoc());
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getSuperclass());
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.modifiers);
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getSuperclassType());
+ acceptChildren(visitor, this.bodyDeclarations);
+ }
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the name of the superclass declared in this type
+ * declaration, or null
if there is none (JLS2 API only).
+ *
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ *
+ *
+ * @return the superclass name node, or null
if
+ * there is none
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #getSuperclassType()}, which returns a Type
+ * instead of a Name
.
+ */
+ public Name getSuperclass() {
+ return internalGetSuperclass();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final Name internalGetSuperclass() {
+ supportedOnlyIn2();
+ return this.optionalSuperclassName;
+ }
+
+ /**
+ * Returns the superclass declared in this type
+ * declaration, or null
if there is none (added in JLS3 API).
+ *
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ *
+ *
+ * @return the superclass type node, or null
if
+ * there is none
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public Type getSuperclassType() {
+ unsupportedIn2();
+ return this.optionalSuperclassType;
+ }
+
+ /**
+ * Sets or clears the name of the superclass declared in this type
+ * declaration (JLS2 API only).
+ *
+ * Note that this child is not relevant for interface
+ * declarations (although it does still figure in subtree
+ * equality comparisons).
+ *
+ *
+ * @param superclassName the superclass name node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setSuperclassType(Type)}, which expects a
+ * Type
instead of a Name
.
+ */
+ public void setSuperclass(Name superclassName) {
+ internalSetSuperclass(superclassName);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final void internalSetSuperclass(Name superclassName) {
+ supportedOnlyIn2();
+ ASTNode oldChild = this.optionalSuperclassName;
+ preReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+ this.optionalSuperclassName = superclassName;
+ postReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+ }
+
+ /**
+ * Sets or clears the superclass declared in this type
+ * declaration (added in JLS3 API).
+ *
+ * Note that this child is not relevant for interface declarations
+ * (although it does still figure in subtree equality comparisons).
+ *
+ *
+ * @param superclassType the superclass type node, or null
if
+ * there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public void setSuperclassType(Type superclassType) {
+ unsupportedIn2();
+ ASTNode oldChild = this.optionalSuperclassType;
+ preReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+ this.optionalSuperclassType = superclassType;
+ postReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the ordered list of field declarations of this type
+ * declaration. For a class declaration, these are the
+ * field declarations; for an interface declaration, these are
+ * the constant declarations.
+ *
+ * This convenience method returns this node's body declarations
+ * with non-fields filtered out. Unlike bodyDeclarations
,
+ * this method does not return a live result.
+ *
+ *
+ * @return the (possibly empty) list of field declarations
+ */
+ public FieldDeclaration[] getFields() {
+ List bd = bodyDeclarations();
+ int fieldCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof FieldDeclaration) {
+ fieldCount++;
+ }
+ }
+ FieldDeclaration[] fields = new FieldDeclaration[fieldCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof FieldDeclaration) {
+ fields[next++] = (FieldDeclaration) decl;
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * Returns the ordered list of method declarations of this type
+ * declaration.
+ *
+ * This convenience method returns this node's body declarations
+ * with non-methods filtered out. Unlike bodyDeclarations
,
+ * this method does not return a live result.
+ *
+ *
+ * @return the (possibly empty) list of method (and constructor)
+ * declarations
+ */
+ public FunctionDeclaration[] getMethods() {
+ List bd = bodyDeclarations();
+ int methodCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof FunctionDeclaration) {
+ methodCount++;
+ }
+ }
+ FunctionDeclaration[] methods = new FunctionDeclaration[methodCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof FunctionDeclaration) {
+ methods[next++] = (FunctionDeclaration) decl;
+ }
+ }
+ return methods;
+ }
+
+ /**
+ * Returns the ordered list of member type declarations of this type
+ * declaration.
+ *
+ * This convenience method returns this node's body declarations
+ * with non-types filtered out. Unlike bodyDeclarations
,
+ * this method does not return a live result.
+ *
+ *
+ * @return the (possibly empty) list of member type declarations
+ */
+ public TypeDeclaration[] getTypes() {
+ List bd = bodyDeclarations();
+ int typeCount = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next() instanceof TypeDeclaration) {
+ typeCount++;
+ }
+ }
+ TypeDeclaration[] memberTypes = new TypeDeclaration[typeCount];
+ int next = 0;
+ for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+ Object decl = it.next();
+ if (decl instanceof TypeDeclaration) {
+ memberTypes[next++] = (TypeDeclaration) decl;
+ }
+ }
+ return memberTypes;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AsbtractTypeDeclaration.
+ */
+ ITypeBinding internalResolveBinding() {
+ return this.ast.getBindingResolver().resolveType(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 6 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize()
+ + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.typeName == null ? 0 : getName().treeSize())
+ + (this.optionalSuperclassName == null ? 0 : getSuperclass().treeSize())
+ + (this.optionalSuperclassType == null ? 0 : getSuperclassType().treeSize())
+ + this.bodyDeclarations.listSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeDeclarationStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeDeclarationStatement.java
new file mode 100644
index 0000000..670975d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeDeclarationStatement.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Local type declaration statement AST node type.
+ *
+ * This kind of node is used to convert a type declaration
+ * node into a statement node by wrapping it.
+ *
+ * For JLS2:
+ *
+ * TypeDeclarationStatement:
+ * TypeDeclaration
+ *
+ * For JLS3, the kinds of type declarations grew to include enum declarations:
+ *
+ * TypeDeclarationStatement:
+ * TypeDeclaration
+ * EnumDeclaration
+ *
+ * Although allowed at the AST, not all arrangements of AST nodes are meaningful;
+ * in particular, only class and enum declarations are meaningful in the context of
+ * a block.
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TypeDeclarationStatement extends Statement {
+
+ /**
+ * The "typeDeclaration" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclarationStatement.class, "typeDeclaration", TypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "declaration" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildPropertyDescriptor DECLARATION_PROPERTY =
+ new ChildPropertyDescriptor(TypeDeclarationStatement.class, "declaration", AbstractTypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(TypeDeclarationStatement.class, propertyList);
+ addProperty(TYPE_DECLARATION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(2);
+ createPropertyList(TypeDeclarationStatement.class, propertyList);
+ addProperty(DECLARATION_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The type declaration; lazily initialized; defaults to a unspecified,
+ * but legal, type declaration. In JLS2, corresponds to TYPE_DECLARATION_PROPERTY.
+ * After JLS2, corresponds to DECLARATION_PROPERTY.
+ * @see #typeDeclProperty
+ */
+ private AbstractTypeDeclaration typeDecl = null;
+
+ /**
+ * The child property stored on the typeDecl
instance variable.
+ * In JLS2, corresponds to TYPE_DECLARATION_PROPERTY. After JLS2, corresponds to
+ * DECLARATION_PROPERTY.
+ *
+ * @return the property corresponding to the typeDecl
instance variable;
+ * never null
+ */
+ private ChildPropertyDescriptor typeDeclProperty () {
+ if (getAST().apiLevel() == AST.JLS2_INTERNAL) {
+ return TYPE_DECLARATION_PROPERTY;
+ } else {
+ return DECLARATION_PROPERTY;
+ }
+ }
+
+
+ /**
+ * Creates a new unparented local type declaration statement node owned
+ * by the given AST. By default, the local type declaration is an
+ * unspecified, but legal, type declaration.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeDeclarationStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ *
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_DECLARATION_PROPERTY) {
+ if (get) {
+ return getTypeDeclaration();
+ } else {
+ setTypeDeclaration((TypeDeclaration) child);
+ return null;
+ }
+ }
+ if (property == DECLARATION_PROPERTY) {
+ if (get) {
+ return getDeclaration();
+ } else {
+ setDeclaration((AbstractTypeDeclaration) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TYPE_DECLARATION_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TypeDeclarationStatement result =
+ new TypeDeclarationStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setDeclaration(
+ (AbstractTypeDeclaration) getDeclaration().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getDeclaration());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the abstract type declaration of this local type declaration
+ * statement (added in JLS3 API).
+ *
+ * @return the type declaration node
+ *
+ */
+ public AbstractTypeDeclaration getDeclaration() {
+ if (this.typeDecl == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.typeDecl == null) {
+ preLazyInit();
+ this.typeDecl = new TypeDeclaration(this.ast);
+ postLazyInit(this.typeDecl, typeDeclProperty());
+ }
+ }
+ }
+ return this.typeDecl;
+ }
+
+ /**
+ * Sets the abstract type declaration of this local type declaration
+ * statement (added in JLS3 API).
+ *
+ * @param decl the type declaration node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ *
+ */
+ public void setDeclaration(AbstractTypeDeclaration decl) {
+ if (decl == null) {
+ throw new IllegalArgumentException();
+ }
+ // a TypeDeclarationStatement may occur inside an
+ // TypeDeclaration - must check cycles
+ ASTNode oldChild = this.typeDecl;
+ ChildPropertyDescriptor typeDeclProperty = typeDeclProperty();
+ preReplaceChild(oldChild, decl, typeDeclProperty);
+ this.typeDecl= decl;
+ postReplaceChild(oldChild, decl, typeDeclProperty);
+ }
+
+ /**
+ * Returns the type declaration of this local type declaration
+ * statement (JLS2 API only).
+ *
+ * @return the type declaration node
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #getDeclaration()}, which returns AbstractTypeDeclaration
+ * instead of TypeDeclaration
.
+ */
+ public TypeDeclaration getTypeDeclaration() {
+ return internalGetTypeDeclaration();
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final TypeDeclaration internalGetTypeDeclaration() {
+ supportedOnlyIn2();
+ return (TypeDeclaration) getDeclaration();
+ }
+
+ /**
+ * Sets the type declaration of this local type declaration
+ * statement (JLS2 API only).
+ *
+ * @param decl the type declaration node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #setDeclaration(AbstractTypeDeclaration)} which takes
+ * AbstractTypeDeclaration
instead of
+ * TypeDeclaration
.
+ */
+ public void setTypeDeclaration(TypeDeclaration decl) {
+ internalSetTypeDeclaration(decl);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final void internalSetTypeDeclaration(TypeDeclaration decl) {
+ supportedOnlyIn2();
+ // forward to non-deprecated replacement method
+ setDeclaration(decl);
+ }
+
+ /**
+ * Resolves and returns the binding for the class or interface declared in
+ * this type declaration statement.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public ITypeBinding resolveBinding() {
+ // forward request to the wrapped type declaration
+ AbstractTypeDeclaration d = getDeclaration();
+ if (d instanceof TypeDeclaration) {
+ return ((TypeDeclaration) d).resolveBinding();
+ } else {
+ // shouldn't happen
+ return null;
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.typeDecl == null ? 0 : getDeclaration().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeLiteral.java
new file mode 100644
index 0000000..1c51435
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/TypeLiteral.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type literal AST node type.
+ *
+ *
+ * TypeLiteral:
+ * ( Type | void ) . class
+ *
+ *
+ * Note: This Class only applies to ECMAScript 4 which is not yet supported
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TypeLiteral extends Expression {
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(TypeLiteral.class, "type", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(2);
+ createPropertyList(TypeLiteral.class, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The type; lazily initialized; defaults to a unspecified,
+ * legal type.
+ */
+ private Type type = null;
+
+ /**
+ * Creates a new AST node for a type literal owned by the given
+ * AST. By default, the expression has an unspecified (but legal) type.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ TypeLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return TYPE_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ TypeLiteral result = new TypeLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setType((Type) getType().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ acceptChild(visitor, getType());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the type in this type literal expression.
+ *
+ * @return the type
+ */
+ public Type getType() {
+ if (this.type == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.type == null) {
+ preLazyInit();
+ this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+ postLazyInit(this.type, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.type;
+ }
+
+ /**
+ * Sets the type in this type literal expression to the given type.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.type;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.type = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 1 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.type == null ? 0 : getType().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/UndefinedLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/UndefinedLiteral.java
new file mode 100644
index 0000000..4cffa4f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/UndefinedLiteral.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null literal node.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class UndefinedLiteral extends Expression {
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(1);
+ createPropertyList(UndefinedLiteral.class, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * Creates a new unparented null literal node owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ UndefinedLiteral(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return UNDEFINED_LITERAL;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ UndefinedLiteral result = new UndefinedLiteral(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ visitor.visit(this);
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return BASE_NODE_SIZE;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return memSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableBinding.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableBinding.java
new file mode 100644
index 0000000..0017d11
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableBinding.java
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TagBits;
+import org.eclipse.wst.jsdt.internal.core.JavaElement;
+import org.eclipse.wst.jsdt.internal.core.LocalVariable;
+
+/**
+ * Internal implementation of variable bindings.
+ */
+class VariableBinding implements IVariableBinding {
+
+ private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+ Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
+
+ private org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding binding;
+ private ITypeBinding declaringClass;
+ private String key;
+ private String name;
+ private BindingResolver resolver;
+ private ITypeBinding type;
+
+ VariableBinding(BindingResolver resolver, org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding binding) {
+ this.resolver = resolver;
+ this.binding = binding;
+ }
+
+ /* (non-Javadoc)
+ * @see IVariableBinding#getConstantValue()
+ *
+ */
+ public Object getConstantValue() {
+ return null;
+ }
+
+ /*
+ * @see IVariableBinding#getDeclaringClass()
+ */
+ public ITypeBinding getDeclaringClass() {
+ if (isField()) {
+ if (this.declaringClass == null) {
+ FieldBinding fieldBinding = (FieldBinding) this.binding;
+ this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
+ }
+ return this.declaringClass;
+ } else {
+ return null;
+ }
+ }
+
+ /*
+ * @see IVariableBinding#getDeclaringMethod()
+ */
+ public IFunctionBinding getDeclaringMethod() {
+ if (!isField()) {
+ ASTNode node = this.resolver.findDeclaringNode(this);
+ while (true) {
+ if (node == null) break;
+ switch(node.getNodeType()) {
+ case ASTNode.INITIALIZER :
+ return null;
+ case ASTNode.FUNCTION_DECLARATION :
+ FunctionDeclaration methodDeclaration = (FunctionDeclaration) node;
+ return methodDeclaration.resolveBinding();
+ default:
+ node = node.getParent();
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see IBinding#getJavaElement()
+ */
+ public IJavaScriptElement getJavaElement() {
+ JavaElement element = getUnresolvedJavaElement();
+ if (element == null)
+ return null;
+ return element.resolved(this.binding);
+ }
+
+ /*
+ * @see IBinding#getKey()
+ */
+ public String getKey() {
+ if (this.key == null) {
+ this.key = new String(this.binding.computeUniqueKey());
+ }
+ return this.key;
+ }
+
+ /*
+ * @see IBinding#getKind()
+ */
+ public int getKind() {
+ return IBinding.VARIABLE;
+ }
+
+ /*
+ * @see IBinding#getModifiers()
+ */
+ public int getModifiers() {
+ if (isField()) {
+ return ((FieldBinding) this.binding).getAccessFlags() & VALID_MODIFIERS;
+ }
+ return Modifier.NONE;
+ }
+
+ /*
+ * @see IBinding#getName()
+ */
+ public String getName() {
+ if (this.name == null) {
+ this.name = new String(this.binding.name);
+ }
+ return this.name;
+ }
+
+ /*
+ * @see IVariableBinding#getType()
+ */
+ public ITypeBinding getType() {
+ if (this.type == null) {
+ this.type = this.resolver.getTypeBinding(this.binding.type);
+ }
+ return this.type;
+ }
+
+ private JavaElement getUnresolvedJavaElement() {
+ if (isField()) {
+ // field
+ FieldBinding fieldBinding = (FieldBinding) this.binding;
+ if (fieldBinding.declaringClass == null) return null; // arraylength
+ IType declaringType = (IType) getDeclaringClass().getJavaElement();
+ if (declaringType == null) return null;
+ return (JavaElement) declaringType.getField(getName());
+ }
+ // local variable
+ IFunctionBinding declaringMethod = getDeclaringMethod();
+ if (declaringMethod == null) return null;
+ JavaElement method = (JavaElement) declaringMethod.getJavaElement();
+ if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+ VariableDeclaration localVar = (VariableDeclaration) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
+ if (localVar == null) return null;
+ int nameStart;
+ int nameLength;
+ int sourceStart;
+ int sourceLength;
+ if (localVar instanceof SingleVariableDeclaration) {
+ sourceStart = localVar.getStartPosition();
+ sourceLength = localVar.getLength();
+ SimpleName simpleName = ((SingleVariableDeclaration) localVar).getName();
+ nameStart = simpleName.getStartPosition();
+ nameLength = simpleName.getLength();
+ } else {
+ nameStart = localVar.getStartPosition();
+ nameLength = localVar.getLength();
+ ASTNode node = localVar.getParent();
+ sourceStart = node.getStartPosition();
+ sourceLength = node.getLength();
+ }
+ char[] typeSig = this.binding.type.signature();
+ return new LocalVariable(method, localVar.getName().getIdentifier(), sourceStart, sourceStart+sourceLength-1, nameStart, nameStart+nameLength-1, new String(typeSig));
+ }
+
+ /*
+ * @see IVariableBinding#getVariableDeclaration()
+ *
+ */
+ public IVariableBinding getVariableDeclaration() {
+ if (this.isField()) {
+ FieldBinding fieldBinding = (FieldBinding) this.binding;
+ return this.resolver.getVariableBinding(fieldBinding.original());
+ }
+ return this;
+ }
+
+ /*
+ * @see IVariableBinding#getVariableId()
+ */
+ public int getVariableId() {
+ return this.binding.id;
+ }
+
+ /*
+ * @see IVariableBinding#isParameter()
+ */
+ public boolean isParameter() {
+ return (this.binding.tagBits & TagBits.IsArgument) != 0;
+ }
+ /*
+ * @see IBinding#isDeprecated()
+ */
+ public boolean isDeprecated() {
+ if (isField()) {
+ return ((FieldBinding) this.binding).isDeprecated();
+ }
+ return false;
+ }
+
+ /*
+ * @see IBinding#isEqualTo(Binding)
+ *
+ */
+ public boolean isEqualTo(IBinding other) {
+ if (other == this) {
+ // identical binding - equal (key or no key)
+ return true;
+ }
+ if (other == null) {
+ // other binding missing
+ return false;
+ }
+ if (!(other instanceof VariableBinding)) {
+ return false;
+ }
+ org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBinding) other).binding;
+ if (this.binding instanceof FieldBinding) {
+ if (otherBinding instanceof FieldBinding) {
+ return BindingComparator.isEqual((FieldBinding) this.binding, (FieldBinding) otherBinding);
+ } else {
+ return false;
+ }
+ }
+ else if (this.binding instanceof LocalVariableBinding) {
+ if (otherBinding instanceof LocalVariableBinding) {
+ return BindingComparator.isEqual((LocalVariableBinding) this.binding, (LocalVariableBinding) otherBinding);
+ } else {
+ return false;
+ }
+ }
+ else {
+ if (BindingComparator.isEqual(this.binding, otherBinding)) {
+ IFunctionBinding declaringMethod = this.getDeclaringMethod();
+ IFunctionBinding otherDeclaringMethod = ((VariableBinding) other).getDeclaringMethod();
+ if (declaringMethod == null) {
+ if (otherDeclaringMethod != null) {
+ return false;
+ }
+ return true;
+ }
+ return declaringMethod.isEqualTo(otherDeclaringMethod);
+ }
+ return false;
+ }
+ }
+
+ /*
+ * @see IVariableBinding#isField()
+ */
+ public boolean isField() {
+ return this.binding instanceof FieldBinding;
+ }
+
+ public boolean isGlobal()
+ {
+ return this.binding instanceof LocalVariableBinding && ((LocalVariableBinding)this.binding).declaringScope instanceof CompilationUnitScope;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+ */
+ public boolean isRecovered() {
+ return false;
+ }
+
+ /*
+ * For debugging purpose only.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return this.binding.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclaration.java
new file mode 100644
index 0000000..493d14c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclaration.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+/**
+ * Abstract base class of all AST node types that declare a single local
+ * variable.
+ *
+ *
+ * VariableDeclaration:
+ * SingleVariableDeclaration
+ * VariableDeclarationFragment
+ *
+ *
+ *
+ * @see SingleVariableDeclaration
+ * @see VariableDeclarationFragment
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class VariableDeclaration extends ASTNode {
+
+ /**
+ * Returns structural property descriptor for the "extraDimensions" property
+ * of this node.
+ *
+ * @return the property descriptor
+ *
+ */
+ abstract SimplePropertyDescriptor internalExtraDimensionsProperty();
+
+ /**
+ * Returns structural property descriptor for the "extraDimensions" property
+ * of this node.
+ *
+ * @return the property descriptor
+ *
+ */
+ public final SimplePropertyDescriptor getExtraDimensionsProperty() {
+ return internalExtraDimensionsProperty();
+ }
+
+ /**
+ * Returns structural property descriptor for the "initializer" property
+ * of this node.
+ *
+ * @return the property descriptor
+ *
+ */
+ abstract ChildPropertyDescriptor internalInitializerProperty();
+
+ /**
+ * Returns structural property descriptor for the "initializer" property
+ * of this node.
+ *
+ * @return the property descriptor
+ *
+ */
+ public final ChildPropertyDescriptor getInitializerProperty() {
+ return internalInitializerProperty();
+ }
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ *
+ */
+ abstract ChildPropertyDescriptor internalNameProperty();
+
+ /**
+ * Returns structural property descriptor for the "name" property
+ * of this node.
+ *
+ * @return the property descriptor
+ *
+ */
+ public final ChildPropertyDescriptor getNameProperty() {
+ return internalNameProperty();
+ }
+
+ /**
+ * Creates a new AST node for a variable declaration owned by the given AST.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclaration(AST ast) {
+ super(ast);
+ }
+
+ /**
+ * Returns the name of the variable declared in this variable declaration.
+ *
+ * @return the variable name node
+ */
+ public abstract SimpleName getName();
+
+ /**
+ * Sets the name of the variable declared in this variable declaration
+ * to the given name.
+ *
+ * @param variableName the new variable name
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public abstract void setName(SimpleName variableName);
+
+ /**
+ * Returns the number of extra array dimensions over and above the
+ * explicitly-specified type.
+ *
+ * For example, int x[][]
has a type of
+ * int
and two extra array dimensions;
+ * int[][] x
has a type of int[][]
+ * and zero extra array dimensions. The two constructs have different
+ * ASTs, even though there are really syntactic variants of the same
+ * variable declaration.
+ *
+ *
+ * @return the number of extra array dimensions
+ *
+ */
+ public abstract int getExtraDimensions();
+
+ /**
+ * Sets the number of extra array dimensions over and above the
+ * explicitly-specified type.
+ *
+ * For example, int x[][]
has a type of
+ * int
and two extra array dimensions;
+ * int[][] x
has a type of int[][]
+ * and zero extra array dimensions. The two constructs have different
+ * ASTs, even though there are really syntactic variants of the same
+ * variable declaration.
+ *
+ *
+ * @param dimensions the number of array dimensions
+ * @exception IllegalArgumentException if the number of dimensions is
+ * negative
+ *
+ */
+ public abstract void setExtraDimensions(int dimensions);
+
+ /**
+ * Returns the initializer of this variable declaration, or
+ * null
if there is none.
+ *
+ * @return the initializer expression node, or null
if
+ * there is none
+ */
+ public abstract Expression getInitializer();
+
+ /**
+ * Sets or clears the initializer of this variable declaration.
+ *
+ * @param initializer the initializer expression node, or null
+ * if there is none
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public abstract void setInitializer(Expression initializer);
+
+ /**
+ * Resolves and returns the binding for the variable declared in this
+ * variable declaration.
+ *
+ * Note that bindings are generally unavailable unless requested when the
+ * AST is being built.
+ *
+ *
+ * @return the binding, or null
if the binding cannot be
+ * resolved
+ */
+ public IVariableBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveVariable(this);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationExpression.java
new file mode 100644
index 0000000..c45cec2
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationExpression.java
@@ -0,0 +1,438 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Local variable declaration expression AST node type.
+ *
+ * This kind of node collects together several variable declaration fragments
+ * (VariableDeclarationFragment
) into a single expression
+ * (Expression
), all sharing the same modifiers and base type.
+ * This type of node can be used as the initializer of a
+ * ForStatement
, or wrapped in an ExpressionStatement
+ * to form the equivalent of a VariableDeclarationStatement
.
+ *
+ * For JLS2:
+ *
+ * VariableDeclarationExpression:
+ * { Modifier } Type VariableDeclarationFragment
+ * { , VariableDeclarationFragment }
+ *
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations):
+ *
+ * VariableDeclarationExpression:
+ * { ExtendedModifier } Type VariableDeclarationFragment
+ * { , VariableDeclarationFragment }
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class VariableDeclarationExpression extends Expression {
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ new SimplePropertyDescriptor(VariableDeclarationExpression.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationExpression.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationExpression.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type).
+ *
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationExpression.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationExpression.class, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationExpression.class, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The extended modifiers (element type: IExtendedModifier
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ */
+ private ASTNode.NodeList modifiers = null;
+
+ /**
+ * The modifier flags; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in 3.0.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+ /**
+ * The base type; lazily initialized; defaults to an unspecified,
+ * legal type.
+ */
+ private Type baseType = null;
+
+ /**
+ * The list of variable declaration fragments (element type:
+ * ). Defaults to an empty list.
+ */
+ private ASTNode.NodeList variableDeclarationFragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented local variable declaration expression node
+ * owned by the given AST. By default, the variable declaration has: no
+ * modifiers, an unspecified (but legal) type, and an empty list of variable
+ * declaration fragments (which is syntactically illegal).
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclarationExpression(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return VARIABLE_DECLARATION_EXPRESSION;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ VariableDeclarationExpression result =
+ new VariableDeclarationExpression(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setType((Type) getType().clone(target));
+ result.fragments().addAll(
+ ASTNode.copySubtrees(target, fragments()));
+ return result;
+
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChildren(visitor, variableDeclarationFragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ *
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ *
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: IExtendedModifier
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ *
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from modifiers()
.
+ *
+ *
+ * @return the bit-wise or of Modifier
constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenient method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedModifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedModifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ *
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ *
+ *
+ * @param modifiers the given modifiers (bit-wise or of Modifier
constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a Modifier
nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ supportedOnlyIn2();
+ preValueChange(MODIFIERS_PROPERTY);
+ this.modifierFlags = pmodifiers;
+ postValueChange(MODIFIERS_PROPERTY);
+ }
+
+ /**
+ * Returns the base type declared in this variable declaration.
+ *
+ * N.B. The individual child variable declaration fragments may specify
+ * additional array dimensions. So the type of the variable are not
+ * necessarily exactly this type.
+ *
+ *
+ * @return the base type
+ */
+ public Type getType() {
+ if (this.baseType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.baseType == null) {
+ preLazyInit();
+ this.baseType = this.ast.newInferredType(null);
+ postLazyInit(this.baseType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.baseType;
+ }
+
+ /**
+ * Sets the base type declared in this variable declaration to the given
+ * type.
+ *
+ * @param type the new base type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.baseType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.baseType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of variable declaration fragments in this
+ * expression. Adding and removing nodes from this list affects this node
+ * dynamically. All nodes in this list must be
+ * VariableDeclarationFragment
s; attempts to add any other
+ * type of node will trigger an exception.
+ *
+ * @return the live list of variable declaration fragments in this
+ * expression (element type: VariableDeclarationFragment
)
+ */
+ public List fragments() {
+ return this.variableDeclarationFragments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.baseType == null ? 0 : getType().treeSize())
+ + this.variableDeclarationFragments.listSize();
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationFragment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationFragment.java
new file mode 100644
index 0000000..bd16a60
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationFragment.java
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Variable declaration fragment AST node type, used in field declarations,
+ * local variable declarations, and ForStatement
initializers.
+ * It contrast to SingleVariableDeclaration
, fragments are
+ * missing the modifiers and the type; these are located in the fragment's
+ * parent node.
+ *
+ *
+ * VariableDeclarationFragment:
+ * Identifier { [] } [ = Expression ]
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class VariableDeclarationFragment extends VariableDeclaration {
+
+ /**
+ * The "name" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationFragment.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "extraDimensions" structural property of this node type.
+ *
+ */
+ public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY =
+ new SimplePropertyDescriptor(VariableDeclarationFragment.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+
+ /**
+ * The "initializer" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor INITIALIZER_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationFragment.class, "initializer", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationFragment.class, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+ addProperty(INITIALIZER_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The variable name; lazily initialized; defaults to an unspecified,
+ * legal JavaScript identifier.
+ */
+ private SimpleName variableName = null;
+
+ /**
+ * The number of extra array dimensions that this variable has;
+ * defaults to 0.
+ */
+ private int extraArrayDimensions = 0;
+
+ /**
+ * The initializer expression, or null
if none;
+ * defaults to none.
+ */
+ private Expression optionalInitializer = null;
+
+ /**
+ * Creates a new AST node for a variable declaration fragment owned by the
+ * given AST. By default, the variable declaration has: an unspecified
+ * (but legal) variable name, no initializer, and no extra array dimensions.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclarationFragment(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+ return EXTRA_DIMENSIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ final ChildPropertyDescriptor internalInitializerProperty() {
+ return INITIALIZER_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ *
+ */
+ final ChildPropertyDescriptor internalNameProperty() {
+ return NAME_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == EXTRA_DIMENSIONS_PROPERTY) {
+ if (get) {
+ return getExtraDimensions();
+ } else {
+ setExtraDimensions(value);
+ return 0;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ if (property == INITIALIZER_PROPERTY) {
+ if (get) {
+ return getInitializer();
+ } else {
+ setInitializer((Expression) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return VARIABLE_DECLARATION_FRAGMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ VariableDeclarationFragment result = new VariableDeclarationFragment(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.setName((SimpleName) getName().clone(target));
+ result.setExtraDimensions(getExtraDimensions());
+ result.setInitializer(
+ (Expression) ASTNode.copySubtree(target, getInitializer()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getName());
+ acceptChild(visitor, getInitializer());
+ }
+ visitor.endVisit(this);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public SimpleName getName() {
+ if (this.variableName == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.variableName == null) {
+ preLazyInit();
+ this.variableName = new SimpleName(this.ast);
+ postLazyInit(this.variableName, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.variableName;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setName(SimpleName variableName) {
+ if (variableName == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.variableName;
+ preReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ this.variableName = variableName;
+ postReplaceChild(oldChild, variableName, NAME_PROPERTY);
+ }
+
+ /**
+ * Returns the number of extra array dimensions this variable has over
+ * and above the type specified in the enclosing declaration.
+ *
+ * For example, in the AST for int[] i, j[], k[][]
the
+ * variable declaration fragments for the variables i
,
+ * j
, and k
, have 0, 1, and 2 extra array
+ * dimensions, respectively.
+ *
+ *
+ * @return the number of extra array dimensions this variable has over
+ * and above the type specified in the enclosing declaration
+ *
+ */
+ public int getExtraDimensions() {
+ return this.extraArrayDimensions;
+ }
+
+ /**
+ * Sets the number of extra array dimensions this variable has over
+ * and above the type specified in the enclosing declaration.
+ *
+ * For example, in the AST for int[] i, j[], k[][]
the
+ * variable declaration fragments for the variables i
,
+ * j
, and k
, have 0, 1, and 2 extra array
+ * dimensions, respectively.
+ *
+ *
+ * @param dimensions the given dimensions
+ *
+ */
+ public void setExtraDimensions(int dimensions) {
+ if (dimensions < 0) {
+ throw new IllegalArgumentException();
+ }
+ preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ this.extraArrayDimensions = dimensions;
+ postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public Expression getInitializer() {
+ return this.optionalInitializer;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on VariableDeclaration.
+ */
+ public void setInitializer(Expression initializer) {
+ ASTNode oldChild = this.optionalInitializer;
+ preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ this.optionalInitializer = initializer;
+ postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Operator as free
+ return BASE_NODE_SIZE + 3 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.variableName == null ? 0 : getName().treeSize())
+ + (this.optionalInitializer == null ? 0 : getInitializer().treeSize());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationStatement.java
new file mode 100644
index 0000000..4dc7012
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/VariableDeclarationStatement.java
@@ -0,0 +1,491 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Local variable declaration statement AST node type.
+ *
+ * This kind of node collects several variable declaration fragments
+ * (VariableDeclarationFragment
) into a statement
+ * (Statement
), all sharing the same modifiers and base type.
+ *
+ * For JLS2:
+ *
+ * VariableDeclarationStatement:
+ * { Modifier } Type VariableDeclarationFragment
+ * { , VariableDeclarationFragment } ;
+ *
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations):
+ *
+ * VariableDeclarationStatement:
+ * { ExtendedModifier } Type VariableDeclarationFragment
+ * { , VariableDeclarationFragment } ;
+ *
+ *
+ * Note: This type of node is a convenience of sorts.
+ * An equivalent way to represent the same statement is to use
+ * a VariableDeclarationExpression
+ * wrapped in an ExpressionStatement
.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class VariableDeclarationStatement extends Statement {
+
+ /**
+ * The "modifiers" structural property of this node type (JLS2 API only).
+ *
+ */
+ public static final SimplePropertyDescriptor MODIFIERS_PROPERTY =
+ new SimplePropertyDescriptor(VariableDeclarationStatement.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+
+ public static final ChildPropertyDescriptor JAVADOC_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationStatement.class, "javadoc", JSdoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "modifiers" structural property of this node type (added in JLS3 API).
+ *
+ */
+ public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationStatement.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "type" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor TYPE_PROPERTY =
+ new ChildPropertyDescriptor(VariableDeclarationStatement.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "fragments" structural property of this node type).
+ *
+ */
+ public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY =
+ new ChildListPropertyDescriptor(VariableDeclarationStatement.class, "fragments", VariableDeclarationFragment.class, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_2_0;
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ *
+ */
+ private static final List PROPERTY_DESCRIPTORS_3_0;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationStatement.class, propertyList);
+ addProperty(MODIFIERS_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+ propertyList = new ArrayList(4);
+ createPropertyList(VariableDeclarationStatement.class, propertyList);
+ addProperty(MODIFIERS2_PROPERTY, propertyList);
+ addProperty(TYPE_PROPERTY, propertyList);
+ addProperty(FRAGMENTS_PROPERTY, propertyList);
+ addProperty(JAVADOC_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ if (apiLevel == AST.JLS2_INTERNAL) {
+ return PROPERTY_DESCRIPTORS_2_0;
+ } else {
+ return PROPERTY_DESCRIPTORS_3_0;
+ }
+ }
+
+ /**
+ * The extended modifiers (element type: IExtendedModifier
).
+ * Null in JLS2. Added in JLS3; defaults to an empty list
+ * (see constructor).
+ *
+ */
+ private ASTNode.NodeList modifiers = null;
+
+ /**
+ * The modifier flagss; bit-wise or of Modifier flags.
+ * Defaults to none. Not used in JLS3.
+ */
+ private int modifierFlags = Modifier.NONE;
+
+
+ JSdoc optionalDocComment = null;
+
+ /**
+ * The base type; lazily initialized; defaults to an unspecified,
+ * legal type.
+ */
+ private Type baseType = null;
+
+ /**
+ * The list of variable variable declaration fragments (element type:
+ * ). Defaults to an empty list.
+ */
+ private ASTNode.NodeList variableDeclarationFragments =
+ new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+ /**
+ * Creates a new unparented local variable declaration statement node owned
+ * by the given AST. By default, the variable declaration has: no modifiers,
+ * an unspecified (but legal) type, and an empty list of variable
+ * declaration fragments (which is syntactically illegal).
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ VariableDeclarationStatement(AST ast) {
+ super(ast);
+ if (ast.apiLevel >= AST.JLS3) {
+ this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+ }
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+ if (property == MODIFIERS_PROPERTY) {
+ if (get) {
+ return getModifiers();
+ } else {
+ setModifiers(value);
+ return 0;
+ }
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetSetIntProperty(property, get, value);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == TYPE_PROPERTY) {
+ if (get) {
+ return getType();
+ } else {
+ setType((Type) child);
+ return null;
+ }
+ }
+ if (property == JAVADOC_PROPERTY) {
+ if (get) {
+ return getJavadoc();
+ } else {
+ setJavadoc((JSdoc) child);
+ return null;
+ }
+ }
+
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == MODIFIERS2_PROPERTY) {
+ return modifiers();
+ }
+ if (property == FRAGMENTS_PROPERTY) {
+ return fragments();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return VARIABLE_DECLARATION_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ VariableDeclarationStatement result =
+ new VariableDeclarationStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+ result.setModifiers(getModifiers());
+ }
+ if (this.ast.apiLevel >= AST.JLS3) {
+ result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+ }
+ result.setType((Type) getType().clone(target));
+ result.setJavadoc(
+ (JSdoc) ASTNode.copySubtree(target, getJavadoc()));
+ result.fragments().addAll(
+ ASTNode.copySubtrees(target, fragments()));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ if (this.ast.apiLevel >= AST.JLS3) {
+ acceptChildren(visitor, this.modifiers);
+ }
+ acceptChild(visitor, getType());
+ acceptChild(visitor, getJavadoc());
+ acceptChildren(visitor, this.variableDeclarationFragments);
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the live ordered list of modifiers and annotations
+ * of this declaration (added in JLS3 API).
+ *
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ *
+ *
+ * @return the live list of modifiers and annotations
+ * (element type: IExtendedModifier
)
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2 AST
+ *
+ */
+ public List modifiers() {
+ // more efficient than just calling unsupportedIn2() to check
+ if (this.modifiers == null) {
+ unsupportedIn2();
+ }
+ return this.modifiers;
+ }
+
+ /**
+ * Returns the modifiers explicitly specified on this declaration.
+ *
+ * In the JLS3 API, this method is a convenience method that
+ * computes these flags from modifiers()
.
+ *
+ *
+ * @return the bit-wise or of Modifier
constants
+ * @see Modifier
+ */
+ public int getModifiers() {
+ // more efficient than checking getAST().API_LEVEL
+ if (this.modifiers == null) {
+ // JLS2 behavior - bona fide property
+ return this.modifierFlags;
+ } else {
+ // JLS3 behavior - convenience method
+ // performance could be improved by caching computed flags
+ // but this would require tracking changes to this.modifiers
+ int computedModifierFlags = Modifier.NONE;
+ for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+ Object x = it.next();
+ if (x instanceof Modifier) {
+ computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+ }
+ }
+ return computedModifierFlags;
+ }
+ }
+
+ /**
+ * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+ *
+ * Note that the final modifier is the only meaningful modifier for local
+ * variable declarations.
+ *
+ *
+ * @param modifiers the given modifiers (bit-wise or of Modifier
constants)
+ * @exception UnsupportedOperationException if this operation is used in
+ * an AST later than JLS2
+ * @see Modifier
+ * @deprecated In the JLS3 API, this method is replaced by
+ * {@link #modifiers()} which contains a list of a Modifier
nodes.
+ */
+ public void setModifiers(int modifiers) {
+ internalSetModifiers(modifiers);
+ }
+
+ /**
+ * Internal synonym for deprecated method. Used to avoid
+ * deprecation warnings.
+ *
+ */
+ /*package*/ final void internalSetModifiers(int pmodifiers) {
+ supportedOnlyIn2();
+ preValueChange(MODIFIERS_PROPERTY);
+ this.modifierFlags = pmodifiers;
+ postValueChange(MODIFIERS_PROPERTY);
+ }
+
+ /**
+ * Returns the base type declared in this variable declaration statement.
+ *
+ * N.B. The individual child variable declaration fragments may specify
+ * additional array dimensions. So the type of the variable are not
+ * necessarily exactly this type.
+ *
+ *
+ * @return the base type
+ */
+ public Type getType() {
+ if (this.baseType == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.baseType == null) {
+ preLazyInit();
+ this.baseType = this.ast.newInferredType(null);
+ postLazyInit(this.baseType, TYPE_PROPERTY);
+ }
+ }
+ }
+ return this.baseType;
+ }
+
+ /**
+ * Sets the base type declared in this variable declaration statement to
+ * the given type.
+ *
+ * @param type the new base type
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ *
+ */
+ public void setType(Type type) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.baseType;
+ preReplaceChild(oldChild, type, TYPE_PROPERTY);
+ this.baseType = type;
+ postReplaceChild(oldChild, type, TYPE_PROPERTY);
+ }
+
+ /**
+ * Returns the live list of variable declaration fragments in this statement.
+ * Adding and removing nodes from this list affects this node dynamically.
+ * All nodes in this list must be VariableDeclarationFragment
s;
+ * attempts to add any other type of node will trigger an
+ * exception.
+ *
+ * @return the live list of variable declaration fragments in this
+ * statement (element type: VariableDeclarationFragment
)
+ */
+ public List fragments() {
+ return this.variableDeclarationFragments;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 4 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.modifiers == null ? 0 : this.modifiers.listSize())
+ + (this.baseType == null ? 0 : getType().treeSize())
+ + this.variableDeclarationFragments.listSize();
+ }
+
+ public IVariableBinding resolveBinding() {
+ return this.ast.getBindingResolver().resolveVariable(this);
+ }
+
+ /**
+ * Returns the doc comment node.
+ *
+ * @return the doc comment node, or null
if none
+ */
+ public JSdoc getJavadoc() {
+ return this.optionalDocComment;
+ }
+
+ /**
+ * Sets or clears the doc comment node.
+ *
+ * @param docComment the doc comment node, or null
if none
+ * @exception IllegalArgumentException if the doc comment string is invalid
+ */
+ public void setJavadoc(JSdoc docComment) {
+ ChildPropertyDescriptor p = internalJavadocProperty();
+ ASTNode oldChild = this.optionalDocComment;
+ preReplaceChild(oldChild, docComment, p);
+ this.optionalDocComment = docComment;
+ postReplaceChild(oldChild, docComment, p);
+ }
+ final ChildPropertyDescriptor internalJavadocProperty() {
+ return JAVADOC_PROPERTY;
+ }
+
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/WhileStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/WhileStatement.java
new file mode 100644
index 0000000..cdbe439
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/WhileStatement.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * While statement AST node type.
+ *
+ *
+ * WhileStatement:
+ * while ( Expression ) Statement
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class WhileStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(WhileStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(WhileStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(WhileStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new unparented while statement node owned by the given
+ * AST. By default, the expresssion is unspecified, but legal, and
+ * the body statement is an empty block.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ WhileStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return WHILE_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ WhileStatement result = new WhileStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody((Statement) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this while statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this while statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this while statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this while statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the body of a while statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the body of a WhileStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/WithStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/WithStatement.java
new file mode 100644
index 0000000..18cc553
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/WithStatement.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * With statement AST node type.
+ *
+ *
+ * WithStatement:
+ * with ( Expression ) Statement
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class WithStatement extends Statement {
+
+ /**
+ * The "expression" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+ new ChildPropertyDescriptor(WithStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "body" structural property of this node type.
+ *
+ */
+ public static final ChildPropertyDescriptor BODY_PROPERTY =
+ new ChildPropertyDescriptor(WithStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(3);
+ createPropertyList(WithStatement.class, propertyList);
+ addProperty(EXPRESSION_PROPERTY, propertyList);
+ addProperty(BODY_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * AST.JLS*
constants
+
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ *
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The expression; lazily initialized; defaults to an unspecified, but
+ * legal, expression.
+ */
+ private Expression expression = null;
+
+ /**
+ * The body statement; lazily initialized; defaults to an empty block
+ * statement.
+ */
+ private Statement body = null;
+
+ /**
+ * Creates a new unparented with statement node owned by the given
+ * AST. By default, the expresssion is unspecified, but legal, and
+ * the body statement is an empty block.
+ *
+ * N.B. This constructor is package-private.
+ *
+ *
+ * @param ast the AST that is to own this node
+ */
+ WithStatement(AST ast) {
+ super(ast);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == EXPRESSION_PROPERTY) {
+ if (get) {
+ return getExpression();
+ } else {
+ setExpression((Expression) child);
+ return null;
+ }
+ }
+ if (property == BODY_PROPERTY) {
+ if (get) {
+ return getBody();
+ } else {
+ setBody((Statement) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final int getNodeType0() {
+ return WITH_STATEMENT;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ ASTNode clone0(AST target) {
+ WithStatement result = new WithStatement(target);
+ result.setSourceRange(this.getStartPosition(), this.getLength());
+ result.copyLeadingComment(this);
+ result.setExpression((Expression) getExpression().clone(target));
+ result.setBody((Statement) getBody().clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getExpression());
+ acceptChild(visitor, getBody());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the expression of this with statement.
+ *
+ * @return the expression node
+ */
+ public Expression getExpression() {
+ if (this.expression == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.expression == null) {
+ preLazyInit();
+ this.expression = new SimpleName(this.ast);
+ postLazyInit(this.expression, EXPRESSION_PROPERTY);
+ }
+ }
+ }
+ return this.expression;
+ }
+
+ /**
+ * Sets the expression of this with statement.
+ *
+ * @param expression the expression node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setExpression(Expression expression) {
+ if (expression == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.expression;
+ preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ this.expression = expression;
+ postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+ }
+
+ /**
+ * Returns the body of this with statement.
+ *
+ * @return the body statement node
+ */
+ public Statement getBody() {
+ if (this.body == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.body == null) {
+ preLazyInit();
+ this.body = new Block(this.ast);
+ postLazyInit(this.body, BODY_PROPERTY);
+ }
+ }
+ }
+ return this.body;
+ }
+
+ /**
+ * Sets the body of this with statement.
+ *
+ * Special note: The JavaScript language does not allow a local variable declaration
+ * to appear as the body of a with statement (they may only appear within a
+ * block). However, the AST will allow a VariableDeclarationStatement
+ * as the body of a WithStatement
. To get something that will
+ * compile, be sure to embed the VariableDeclarationStatement
+ * inside a Block
.
+ *
+ *
+ * @param statement the body statement node
+ * @exception IllegalArgumentException if:
+ *
+ * - the node belongs to a different AST
+ * - the node already has a parent
+ * - a cycle in would be created
+ *
+ */
+ public void setBody(Statement statement) {
+ if (statement == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.body;
+ preReplaceChild(oldChild, statement, BODY_PROPERTY);
+ this.body = statement;
+ postReplaceChild(oldChild, statement, BODY_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ return super.memSize() + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.expression == null ? 0 : getExpression().treeSize())
+ + (this.body == null ? 0 : getBody().treeSize());
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ASTRewrite.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ASTRewrite.java
new file mode 100644
index 0000000..40ef561
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ASTRewrite.java
@@ -0,0 +1,653 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom.rewrite;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
+import org.eclipse.wst.jsdt.core.ITypeRoot;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.dom.AST;
+import org.eclipse.wst.jsdt.core.dom.ASTNode;
+import org.eclipse.wst.jsdt.core.dom.Block;
+import org.eclipse.wst.jsdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+import org.eclipse.wst.jsdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.LineInformation;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.NodeInfoStore;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.NodeRewriteEvent;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.TrackedNodePosition;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+
+/**
+ * Infrastructure for modifying code by describing changes to AST nodes.
+ * The AST rewriter collects descriptions of modifications to nodes and
+ * translates these descriptions into text edits that can then be applied to
+ * the original source. The key thing is that this is all done without actually
+ * modifying the original AST, which has the virtue of allowing one to entertain
+ * several alternate sets of changes on the same AST (e.g., for calculating
+ * quick fix proposals). The rewrite infrastructure tries to generate minimal
+ * text changes, preserve existing comments and indentation, and follow code
+ * formatter settings. If the freedom to explore multiple alternate changes is
+ * not required, consider using the AST's built-in rewriter
+ * (see {@link org.eclipse.wst.jsdt.core.dom.JavaScriptUnit#rewrite(IDocument, Map)}).
+ *
+ * The following code snippet illustrated usage of this class:
+ *
+ *
+ * Document document = new Document("import java.util.List;\nclass X {}\n");
+ * ASTParser parser = ASTParser.newParser(AST.JLS3);
+ * parser.setSource(doc.get().toCharArray());
+ * JavaScriptUnit cu = (JavaScriptUnit) parser.createAST(null);
+ * AST ast = cu.getAST();
+ * ImportDeclaration id = ast.newImportDeclaration();
+ * id.setName(ast.newName(new String[] {"java", "util", "Set"}));
+ * ASTRewrite rewriter = ASTRewrite.create(ast);
+ * TypeDeclaration td = (TypeDeclaration) cu.types().get(0);
+ * ITrackedNodePosition tdLocation = rewriter.track(td);
+ * ListRewrite lrw = rewriter.getListRewrite(cu, JavaScriptUnit.IMPORTS_PROPERTY);
+ * lrw.insertLast(id, null);
+ * TextEdit edits = rewriter.rewriteAST(document, null);
+ * UndoEdit undo = edits.apply(document);
+ * assert "import java.util.List;\nimport java.util.Set;\nclass X {}".equals(doc.get().toCharArray());
+ * // tdLocation.getStartPosition() and tdLocation.getLength()
+ * // are new source range for "class X {}" in doc.get()
+ *
+ *
+ * This class is not intended to be subclassed.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ASTRewrite {
+
+ /** root node for the rewrite: Only nodes under this root are accepted */
+ private final AST ast;
+
+ private final RewriteEventStore eventStore;
+ private final NodeInfoStore nodeStore;
+
+ /**
+ * Target source range computer; null means uninitialized;
+ * lazy initialized to new TargetSourceRangeComputer()
.
+ */
+ private TargetSourceRangeComputer targetSourceRangeComputer = null;
+
+ /**
+ * Creates a new instance for describing manipulations of
+ * the given AST.
+ *
+ * @param ast the AST whose nodes will be rewritten
+ * @return the new rewriter instance
+ */
+ public static ASTRewrite create(AST ast) {
+ return new ASTRewrite(ast);
+ }
+
+ /**
+ * Internal constructor. Creates a new instance for the given AST.
+ * Clients should use {@link #create(AST)} to create instances.
+ *
+ * @param ast the AST being rewritten
+ */
+ protected ASTRewrite(AST ast) {
+ this.ast= ast;
+ this.eventStore= new RewriteEventStore();
+ this.nodeStore= new NodeInfoStore(ast);
+ }
+
+ /**
+ * Returns the AST the rewrite was set up on.
+ *
+ * @return the AST the rewrite was set up on
+ */
+ public final AST getAST() {
+ return this.ast;
+ }
+
+ /**
+ * Internal method. Returns the internal event store.
+ * Clients should not use.
+ * @return Returns the internal event store. Clients should not use.
+ */
+ protected final RewriteEventStore getRewriteEventStore() {
+ return this.eventStore;
+ }
+
+ /**
+ * Internal method. Returns the internal node info store.
+ * Clients should not use.
+ * @return Returns the internal info store. Clients should not use.
+ */
+ protected final NodeInfoStore getNodeStore() {
+ return this.nodeStore;
+ }
+
+ /**
+ * Converts all modifications recorded by this rewriter
+ * into an object representing the corresponding text
+ * edits to the given document containing the original source
+ * code. The document itself is not modified.
+ *
+ * For nodes in the original that are being replaced or deleted,
+ * this rewriter computes the adjusted source ranges
+ * by calling getTargetSourceRangeComputer().computeSourceRange(node)
.
+ *
+ *
+ * Calling this methods does not discard the modifications
+ * on record. Subsequence modifications are added to the ones
+ * already on record. If this method is called again later,
+ * the resulting text edit object will accurately reflect
+ * the net cumulative affect of all those changes.
+ *
+ *
+ * @param document original document containing source code
+ * @param options the table of formatter options
+ * (key type: String
; value type: String
);
+ * or null
to use the standard global options
+ * {@link org.eclipse.wst.jsdt.core.JavaScriptCore#getOptions() org.eclipse.wst.jsdt.core.JavaScriptCore.getOptions()}
+ * @return text edit object describing the changes to the
+ * document corresponding to the changes recorded by this rewriter
+ * @throws IllegalArgumentException An IllegalArgumentException
+ * is thrown if the document passed does not correspond to the AST that is rewritten.
+ */
+ public TextEdit rewriteAST(IDocument document, Map options) throws IllegalArgumentException {
+ if (document == null) {
+ throw new IllegalArgumentException();
+ }
+
+ ASTNode rootNode= getRootNode();
+ if (rootNode == null) {
+ return new MultiTextEdit(); // no changes
+ }
+
+ char[] content= document.get().toCharArray();
+ LineInformation lineInfo= LineInformation.create(document);
+ String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+
+ ASTNode astRoot= rootNode.getRoot();
+ List commentNodes= astRoot instanceof JavaScriptUnit ? ((JavaScriptUnit) astRoot).getCommentList() : null;
+ return internalRewriteAST(content, lineInfo, lineDelim, commentNodes, options, rootNode);
+ }
+
+ /**
+ * Converts all modifications recorded by this rewriter into an object representing the the corresponding text
+ * edits to the source of a {@link ITypeRoot} from which the AST was created from.
+ * The type root's source itself is not modified by this method call.
+ *
+ * Important: This API can only be used if the modified AST has been created from a
+ * {@link ITypeRoot} with source. That means {@link org.eclipse.wst.jsdt.core.dom.ASTParser#setSource(org.eclipse.wst.jsdt.core.IJavaScriptUnit)},
+ * {@link org.eclipse.wst.jsdt.core.dom.ASTParser#setSource(org.eclipse.wst.jsdt.core.IClassFile)} or {@link org.eclipse.wst.jsdt.core.dom.ASTParser#setSource(ITypeRoot)}
+ * has been used when initializing the {@link org.eclipse.wst.jsdt.core.dom.ASTParser}. A {@link IllegalArgumentException} is thrown
+ * otherwise. An {@link IllegalArgumentException} is also thrown when the type roots buffer does not correspond
+ * anymore to the AST. Use {@link #rewriteAST(IDocument, Map)} for all ASTs created from other content.
+ *
+ *
+ * For nodes in the original that are being replaced or deleted,
+ * this rewriter computes the adjusted source ranges
+ * by calling getTargetSourceRangeComputer().computeSourceRange(node)
.
+ *
+ *
+ * Calling this methods does not discard the modifications
+ * on record. Subsequence modifications are added to the ones
+ * already on record. If this method is called again later,
+ * the resulting text edit object will accurately reflect
+ * the net cumulative affect of all those changes.
+ *
+ *
+ * @return text edit object describing the changes to the
+ * document corresponding to the changes recorded by this rewriter
+ * @throws JavaScriptModelException A {@link JavaScriptModelException} is thrown when
+ * the underlying javaScript units buffer could not be accessed.
+ * @throws IllegalArgumentException An {@link IllegalArgumentException}
+ * is thrown if the document passed does not correspond to the AST that is rewritten.
+ *
+ */
+ public TextEdit rewriteAST() throws JavaScriptModelException, IllegalArgumentException {
+ ASTNode rootNode= getRootNode();
+ if (rootNode == null) {
+ return new MultiTextEdit(); // no changes
+ }
+
+ ASTNode root= rootNode.getRoot();
+ if (!(root instanceof JavaScriptUnit)) {
+ throw new IllegalArgumentException("This API can only be used if the AST is created from a javaScript unit or class file"); //$NON-NLS-1$
+ }
+ JavaScriptUnit astRoot= (JavaScriptUnit) root;
+ ITypeRoot typeRoot = astRoot.getTypeRoot();
+ if (typeRoot == null || typeRoot.getBuffer() == null) {
+ throw new IllegalArgumentException("This API can only be used if the AST is created from a javaScript unit or class file"); //$NON-NLS-1$
+ }
+
+ char[] content= typeRoot.getBuffer().getCharacters();
+ LineInformation lineInfo= LineInformation.create(astRoot);
+ String lineDelim= typeRoot.findRecommendedLineSeparator();
+ Map options= typeRoot.getJavaScriptProject().getOptions(true);
+
+ return internalRewriteAST(content, lineInfo, lineDelim, astRoot.getCommentList(), options, rootNode);
+ }
+
+ private TextEdit internalRewriteAST(char[] content, LineInformation lineInfo, String lineDelim, List commentNodes, Map options, ASTNode rootNode) {
+ TextEdit result= new MultiTextEdit();
+ //validateASTNotModified(rootNode);
+
+ TargetSourceRangeComputer sourceRangeComputer= getExtendedSourceRangeComputer();
+ this.eventStore.prepareMovedNodes(sourceRangeComputer);
+
+ ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, commentNodes, options, sourceRangeComputer);
+ rootNode.accept(visitor); // throws IllegalArgumentException
+
+ this.eventStore.revertMovedNodes();
+ return result;
+ }
+
+ private ASTNode getRootNode() {
+ ASTNode node= null;
+ int start= -1;
+ int end= -1;
+
+ for (Iterator iter= getRewriteEventStore().getChangeRootIterator(); iter.hasNext();) {
+ ASTNode curr= (ASTNode) iter.next();
+ if (!RewriteEventStore.isNewNode(curr)) {
+ int currStart= curr.getStartPosition();
+ int currEnd= currStart + curr.getLength();
+ if (node == null || currStart < start && currEnd > end) {
+ start= currStart;
+ end= currEnd;
+ node= curr;
+ } else if (currStart < start) {
+ start= currStart;
+ } else if (currEnd > end) {
+ end= currEnd;
+ }
+ }
+ }
+ if (node != null) {
+ int currStart= node.getStartPosition();
+ int currEnd= currStart + node.getLength();
+ while (start < currStart || end > currEnd) { // go up until a node covers all
+ node= node.getParent();
+ currStart= node.getStartPosition();
+ currEnd= currStart + node.getLength();
+ }
+ ASTNode parent= node.getParent(); // go up until a parent has different range
+ while (parent != null && parent.getStartPosition() == node.getStartPosition() && parent.getLength() == node.getLength()) {
+ node= parent;
+ parent= node.getParent();
+ }
+ }
+ return node;
+ }
+
+ /*
+ private void validateASTNotModified(ASTNode root) throws IllegalArgumentException {
+ GenericVisitor isModifiedVisitor= new GenericVisitor() {
+ protected boolean visitNode(ASTNode node) {
+ if ((node.getFlags() & ASTNode.ORIGINAL) == 0) {
+ throw new IllegalArgumentException("The AST that is rewritten must not be modified."); //$NON-NLS-1$
+ }
+ return true;
+ }
+ };
+ root.accept(isModifiedVisitor);
+ }
+ */
+
+ /**
+ * Removes the given node from its parent in this rewriter. The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node should not be there.
+ *
+ * @param node the node being removed
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not
+ * part of this rewriter's AST, or if the described modification is invalid
+ * (such as removing a required node)
+ */
+ public final void remove(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ StructuralPropertyDescriptor property= node.getLocationInParent();
+ if (property.isChildListProperty()) {
+ getListRewrite(node.getParent(), (ChildListPropertyDescriptor) property).remove(node, editGroup);
+ } else {
+ set(node.getParent(), property, null, editGroup);
+ }
+ }
+
+ /**
+ * Replaces the given node in this rewriter. The replacement node
+ * must either be brand new (not part of the original AST) or a placeholder
+ * node (for example, one created by {@link #createCopyTarget(ASTNode)}
+ * or {@link #createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been replaced.
+ *
+ * @param node the node being replaced
+ * @param replacement the replacement node, or null
if no
+ * replacement
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the replacement node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ */
+ public final void replace(ASTNode node, ASTNode replacement, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ StructuralPropertyDescriptor property= node.getLocationInParent();
+ if (property.isChildListProperty()) {
+ getListRewrite(node.getParent(), (ChildListPropertyDescriptor) property).replace(node, replacement, editGroup);
+ } else {
+ set(node.getParent(), property, replacement, editGroup);
+ }
+ }
+
+ /**
+ * Sets the given property of the given node. If the given property is a child
+ * property, the value must be a replacement node that is either be brand new
+ * (not part of the original AST) or a placeholder node (for example, one
+ * created by {@link #createCopyTarget(ASTNode)}
+ * or {@link #createStringPlaceholder(String, int)}); or it must be
+ * null
, indicating that the child should be deleted.
+ * If the given property is a simple property, the value must be the new
+ * value (primitive types must be boxed) or null
.
+ * The AST itself is not actually modified in any way; rather, the rewriter
+ * just records a note that this node has been changed in the specified way.
+ *
+ * @param node the node
+ * @param property the node's property; either a simple property or a child property
+ * @param value the replacement child or new value, or null
if none
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node or property is null, or if the node
+ * is not part of this rewriter's AST, or if the property is not a node property,
+ * or if the described modification is invalid
+ */
+ public final void set(ASTNode node, StructuralPropertyDescriptor property, Object value, TextEditGroup editGroup) {
+ if (node == null || property == null) {
+ throw new IllegalArgumentException();
+ }
+ validateIsCorrectAST(node);
+ validatePropertyType(property, value);
+
+ NodeRewriteEvent nodeEvent= this.eventStore.getNodeEvent(node, property, true);
+ nodeEvent.setNewValue(value);
+ if (editGroup != null) {
+ this.eventStore.setEventEditGroup(nodeEvent, editGroup);
+ }
+ }
+
+ /**
+ * Returns the value of the given property as managed by this rewriter. If the property
+ * has been removed, null
is returned. If it has been replaced, the replacing value
+ * is returned. If the property has not been changed yet, the original value is returned.
+ *
+ * For child list properties use {@link ListRewrite#getRewrittenList()} to get access to the
+ * rewritten nodes in a list.
+ *
+ * @param node the node
+ * @param property the node's property
+ * @return the value of the given property as managed by this rewriter
+ *
+ */
+ public Object get(ASTNode node, StructuralPropertyDescriptor property) {
+ if (node == null || property == null) {
+ throw new IllegalArgumentException();
+ }
+ if (property.isChildListProperty()) {
+ throw new IllegalArgumentException("Use the list rewriter to access nodes in a list"); //$NON-NLS-1$
+ }
+ return this.eventStore.getNewValue(node, property);
+ }
+
+ /**
+ * Creates and returns a new rewriter for describing modifications to the
+ * given list property of the given node.
+ *
+ * @param node the node
+ * @param property the node's property; the child list property
+ * @return a new list rewriter object
+ * @throws IllegalArgumentException if the node or property is null, or if the node
+ * is not part of this rewriter's AST, or if the property is not a node property,
+ * or if the described modification is invalid
+ */
+ public final ListRewrite getListRewrite(ASTNode node, ChildListPropertyDescriptor property) {
+ if (node == null || property == null) {
+ throw new IllegalArgumentException();
+ }
+ validateIsListProperty(property);
+
+ return new ListRewrite(this, node, property);
+ }
+
+ /**
+ * Returns an object that tracks the source range of the given node
+ * across the rewrite to its AST. Upon return, the result object reflects
+ * the given node's current source range in the AST. After
+ * rewrite
is called, the result object is updated to
+ * reflect the given node's source range in the rewritten AST.
+ *
+ * @param node the node to track
+ * @return an object that tracks the source range of node
+ * @throws IllegalArgumentException if the node is null, or if the node
+ * is not part of this rewriter's AST, or if the node is already being
+ * tracked
+ */
+ public final ITrackedNodePosition track(ASTNode node) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ TextEditGroup group= this.eventStore.getTrackedNodeData(node);
+ if (group == null) {
+ group= new TextEditGroup("internal"); //$NON-NLS-1$
+ this.eventStore.setTrackedNodeData(node, group);
+ }
+ return new TrackedNodePosition(group, node);
+ }
+
+ private void validateIsExistingNode(ASTNode node) {
+ if (node.getStartPosition() == -1) {
+ throw new IllegalArgumentException("Node is not an existing node"); //$NON-NLS-1$
+ }
+ }
+
+ private void validateIsCorrectAST(ASTNode node) {
+ if (node.getAST() != getAST()) {
+ throw new IllegalArgumentException("Node is not inside the AST"); //$NON-NLS-1$
+ }
+ }
+
+ private void validateIsListProperty(StructuralPropertyDescriptor property) {
+ if (!property.isChildListProperty()) {
+ String message= property.getId() + " is not a list property"; //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ private void validatePropertyType(StructuralPropertyDescriptor prop, Object node) {
+ if (prop.isChildListProperty()) {
+ String message= "Can not modify a list property, use a list rewriter"; //$NON-NLS-1$
+ throw new IllegalArgumentException(message);
+ }
+// if (node == null) {
+// if (prop.isSimpleProperty() || (prop.isChildProperty() && ((ChildPropertyDescriptor) prop).isMandatory())) {
+// String message= "Can not remove property " + prop.getId();
+// throw new IllegalArgumentException(message);
+// }
+// } else {
+// if (!prop.getNodeClass().isInstance(node)) {
+// String message= node.getClass().getName() + " is not a valid type for property " + prop.getId();
+// throw new IllegalArgumentException(message);
+// }
+// }
+ }
+
+ /**
+ * Creates and returns a placeholder node for a source string that is to be inserted into
+ * the output document at the position corresponding to the placeholder.
+ * The string will be inserted without being reformatted beyond correcting
+ * the indentation level. The placeholder node can either be inserted as new or
+ * used to replace an existing node.
+ *
+ * @param code the string to be inserted; lines should should not have extra indentation
+ * @param nodeType the ASTNode type that corresponds to the passed code.
+ * @return the new placeholder node
+ * @throws IllegalArgumentException if the code is null, or if the node
+ * type is invalid
+ */
+ public final ASTNode createStringPlaceholder(String code, int nodeType) {
+ if (code == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode placeholder= getNodeStore().newPlaceholderNode(nodeType);
+ if (placeholder == null) {
+ throw new IllegalArgumentException("String placeholder is not supported for type" + nodeType); //$NON-NLS-1$
+ }
+
+ getNodeStore().markAsStringPlaceholder(placeholder, code);
+ return placeholder;
+ }
+
+ /**
+ * Creates and returns a node that represents a sequence of nodes.
+ * Each of the given nodes must be either be brand new (not part of the original AST), or
+ * a placeholder node (for example, one created by {@link #createCopyTarget(ASTNode)}
+ * or {@link #createStringPlaceholder(String, int)}), or another group node.
+ * The type of the returned node is unspecified. The returned node can be used
+ * to replace an existing node (or as an element of another group node).
+ * When the document is rewritten, the source code for each of the given nodes is
+ * inserted, in order, into the output document at the position corresponding to the
+ * group (indentation is adjusted).
+ *
+ * @param targetNodes the nodes to go in the group
+ * @return the new group node
+ * @throws IllegalArgumentException if the targetNodes is null
or empty
+ */
+ public final ASTNode createGroupNode(ASTNode[] targetNodes) {
+ if (targetNodes == null || targetNodes.length == 0) {
+ throw new IllegalArgumentException();
+ }
+ Block res= getNodeStore().createCollapsePlaceholder();
+ ListRewrite listRewrite= getListRewrite(res, Block.STATEMENTS_PROPERTY);
+ for (int i= 0; i < targetNodes.length; i++) {
+ listRewrite.insertLast(targetNodes[i], null);
+ }
+ return res;
+ }
+
+
+ private ASTNode createTargetNode(ASTNode node, boolean isMove) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ validateIsExistingNode(node);
+ validateIsCorrectAST(node);
+ CopySourceInfo info= getRewriteEventStore().markAsCopySource(node.getParent(), node.getLocationInParent(), node, isMove);
+
+ ASTNode placeholder= getNodeStore().newPlaceholderNode(node.getNodeType());
+ if (placeholder == null) {
+ throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + node.getClass().getName()); //$NON-NLS-1$
+ }
+ getNodeStore().markAsCopyTarget(placeholder, info);
+
+ return placeholder;
+ }
+
+ /**
+ * Creates and returns a placeholder node for a true copy of the given node.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param node the node to create a copy placeholder for
+ * @return the new placeholder node
+ * @throws IllegalArgumentException if the node is null, or if the node
+ * is not part of this rewriter's AST
+ */
+ public final ASTNode createCopyTarget(ASTNode node) {
+ return createTargetNode(node, false);
+ }
+
+ /**
+ * Creates and returns a placeholder node for the new locations of the given node.
+ * After obtaining a placeholder, the node should then to be removed or replaced.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, the source code for the given
+ * node is inserted into the output document at the position corresponding to the
+ * placeholder (indentation is adjusted).
+ *
+ * @param node the node to create a move placeholder for
+ * @return the new placeholder node
+ * @throws IllegalArgumentException if the node is null, or if the node
+ * is not part of this rewriter's AST
+ */
+ public final ASTNode createMoveTarget(ASTNode node) {
+ return createTargetNode(node, true);
+ }
+
+ /**
+ * Returns the extended source range computer for this AST rewriter.
+ * The default value is a new TargetSourceRangeComputer()
.
+ *
+ * @return an extended source range computer
+ */
+ public final TargetSourceRangeComputer getExtendedSourceRangeComputer() {
+ if (this.targetSourceRangeComputer == null) {
+ // lazy initialize
+ this.targetSourceRangeComputer = new TargetSourceRangeComputer();
+ }
+ return this.targetSourceRangeComputer;
+ }
+
+ /**
+ * Sets a custom target source range computer for this AST rewriter. This is advanced feature to modify how
+ * comments are associated with nodes, which should be done only in special cases.
+ *
+ * @param computer a target source range computer,
+ * or null
to restore the default value of
+ * new TargetSourceRangeComputer()
+ */
+ public final void setTargetSourceRangeComputer(TargetSourceRangeComputer computer) {
+ // if computer==null, rely on lazy init code in getTargetSourceRangeComputer()
+ this.targetSourceRangeComputer = computer;
+ }
+
+ /**
+ * Returns a string suitable for debugging purposes (only).
+ *
+ * @return a debug string
+ */
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ buf.append("Events:\n"); //$NON-NLS-1$
+ // be extra careful of uninitialized or mangled instances
+ if (this.eventStore != null) {
+ buf.append(this.eventStore.toString());
+ }
+ return buf.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ITrackedNodePosition.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ITrackedNodePosition.java
new file mode 100644
index 0000000..3295eb8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ITrackedNodePosition.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom.rewrite;
+
+/**
+ * A tracked node position is returned when a rewrite change is
+ * requested to be tracked.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * @see ASTRewrite#track(org.eclipse.wst.jsdt.core.dom.ASTNode)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface ITrackedNodePosition {
+
+ /**
+ * Returns the original or modified start position of the tracked node depending if called before
+ * or after the rewrite is applied. -1
is returned for removed nodes.
+ *
+ * @return the original or modified start position of the tracked node
+ */
+ public int getStartPosition();
+
+ /**
+ * Returns the original or modified length of the tracked node depending if called before
+ * or after the rewrite is applied. -1
is returned for removed nodes.
+ *
+ * @return the original or modified length of the tracked node
+ */
+ public int getLength();
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ImportRewrite.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ImportRewrite.java
new file mode 100644
index 0000000..0652514
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ImportRewrite.java
@@ -0,0 +1,1030 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.dom.rewrite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.jsdt.core.Flags;
+import org.eclipse.wst.jsdt.core.IImportDeclaration;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.ITypeRoot;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.Signature;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.dom.AST;
+import org.eclipse.wst.jsdt.core.dom.ASTParser;
+import org.eclipse.wst.jsdt.core.dom.IBinding;
+import org.eclipse.wst.jsdt.core.dom.IFunctionBinding;
+import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
+import org.eclipse.wst.jsdt.core.dom.IVariableBinding;
+import org.eclipse.wst.jsdt.core.dom.ImportDeclaration;
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+import org.eclipse.wst.jsdt.core.dom.Modifier;
+import org.eclipse.wst.jsdt.core.dom.PrimitiveType;
+import org.eclipse.wst.jsdt.core.dom.Type;
+import org.eclipse.wst.jsdt.core.infer.IInferenceFile;
+import org.eclipse.wst.jsdt.core.infer.ImportRewriteSupport;
+import org.eclipse.wst.jsdt.core.infer.InferrenceManager;
+import org.eclipse.wst.jsdt.core.infer.InferrenceProvider;
+import org.eclipse.wst.jsdt.core.infer.RefactoringSupport;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.ImportRewriteAnalyzer;
+import org.eclipse.wst.jsdt.internal.core.util.Messages;
+
+
+/**
+ * The {@link ImportRewrite} helps updating imports following a import order and on-demand imports threshold as configured by a project.
+ *
+ * The import rewrite is created on a javaScript unit and collects references to types that are added or removed. When adding imports, e.g. using
+ * {@link #addImport(String)}, the import rewrite evaluates if the type can be imported and returns the a reference to the type that can be used in code.
+ * This reference is either unqualified if the import could be added, or fully qualified if the import failed due to a conflict with another element of the same name.
+ *
+ *
+ * On {@link #rewriteImports(IProgressMonitor)} the rewrite translates these descriptions into
+ * text edits that can then be applied to the original source. The rewrite infrastructure tries to generate minimal text changes and only
+ * works on the import statements. It is possible to combine the result of an import rewrite with the result of a {@link org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite}
+ * as long as no import statements are modified by the AST rewrite.
+ *
+ * The options controlling the import order and on-demand thresholds are:
+ *
- {@link #setImportOrder(String[])} specifies the import groups and their preferred order
+ * - {@link #setOnDemandImportThreshold(int)} specifies the number of imports in a group needed for a on-demand import statement (star import)
+ * - {@link #setStaticOnDemandImportThreshold(int)} specifies the number of static imports in a group needed for a on-demand import statement (star import)
+ *
+ * This class is not intended to be subclassed.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class ImportRewrite {
+
+ /**
+ * A {@link ImportRewrite.ImportRewriteContext} can optionally be used in e.g. {@link ImportRewrite#addImport(String, ImportRewrite.ImportRewriteContext)} to
+ * give more information about the types visible in the scope. These types can be for example inherited inner types where it is
+ * unnecessary to add import statements for.
+ *
+ *
+ *
+ * This class can be implemented by clients.
+ *
+ */
+ public static abstract class ImportRewriteContext {
+
+ /**
+ * Result constant signaling that the given element is know in the context.
+ */
+ public final static int RES_NAME_FOUND= 1;
+
+ /**
+ * Result constant signaling that the given element is not know in the context.
+ */
+ public final static int RES_NAME_UNKNOWN= 2;
+
+ /**
+ * Result constant signaling that the given element is conflicting with an other element in the context.
+ */
+ public final static int RES_NAME_CONFLICT= 3;
+
+ /**
+ * Kind constant specifying that the element is a type import.
+ */
+ public final static int KIND_TYPE= 1;
+
+ /**
+ * Kind constant specifying that the element is a static field import.
+ */
+ public final static int KIND_STATIC_FIELD= 2;
+
+ /**
+ * Kind constant specifying that the element is a static method import.
+ */
+ public final static int KIND_STATIC_METHOD= 3;
+
+ /**
+ * Searches for the given element in the context and reports if the element is known ({@link #RES_NAME_FOUND}),
+ * unknown ({@link #RES_NAME_UNKNOWN}) or if its name conflicts ({@link #RES_NAME_CONFLICT}) with an other element.
+ * @param qualifier The qualifier of the element, can be package or the qualified name of a type
+ * @param name The simple name of the element; either a type, method or field name or * for on-demand imports.
+ * @param kind The kind of the element. Can be either {@link #KIND_TYPE}, {@link #KIND_STATIC_FIELD} or
+ * {@link #KIND_STATIC_METHOD}. Implementors should be prepared for new, currently unspecified kinds and return
+ * {@link #RES_NAME_UNKNOWN} by default.
+ * @return Returns the result of the lookup. Can be either {@link #RES_NAME_FOUND}, {@link #RES_NAME_UNKNOWN} or
+ * {@link #RES_NAME_CONFLICT}.
+ */
+ public abstract int findInContext(String qualifier, String name, int kind);
+ }
+
+ private static final char STATIC_PREFIX= 's';
+ private static final char NORMAL_PREFIX= 'n';
+
+ private final ImportRewriteContext defaultContext;
+
+ private final IJavaScriptUnit compilationUnit;
+ private final JavaScriptUnit astRoot;
+
+ private final boolean restoreExistingImports;
+ private final List existingImports;
+
+ private String[] importOrder;
+ private int importOnDemandThreshold;
+ private int staticImportOnDemandThreshold;
+
+ private List addedImports;
+ private List removedImports;
+
+ private String[] createdImports;
+ private String[] createdStaticImports;
+
+ private boolean filterImplicitImports;
+
+ private boolean writeImports=false;
+
+ private ImportRewriteSupport importRewriteExtension;
+ private boolean isImportMatchesType=true;
+
+ /**
+ * Creates a {@link ImportRewrite} from a {@link IJavaScriptUnit}. If restoreExistingImports
+ * is true
, all existing imports are kept, and new imports will be inserted at best matching locations. If
+ * restoreExistingImports
is false
, the existing imports will be removed and only the
+ * newly added imports will be created.
+ *
+ * Note that {@link #create(IJavaScriptUnit, boolean)} is more efficient than this method if an AST for
+ * the javaScript unit is already available.
+ *
+ * @param cu the javaScript unit to create the imports for
+ * @param restoreExistingImports specifies if the existing imports should be kept or removed.
+ * @return the created import rewriter.
+ * @throws JavaScriptModelException thrown when the javaScript unit could not be accessed.
+ */
+ public static ImportRewrite create(IJavaScriptUnit cu, boolean restoreExistingImports) throws JavaScriptModelException {
+ if (cu == null) {
+ throw new IllegalArgumentException("JavaScript unit must not be null"); //$NON-NLS-1$
+ }
+ ImportRewriteSupport importRewriteExtension=null;
+ InferrenceProvider[] inferenceProviders = InferrenceManager.getInstance().getInferenceProviders( (IInferenceFile)cu);
+ if (inferenceProviders.length>0 && inferenceProviders[0].getRefactoringSupport()!=null)
+ {
+ RefactoringSupport refactoringSupport = inferenceProviders[0].getRefactoringSupport();
+ if (refactoringSupport!=null)
+ importRewriteExtension=refactoringSupport.getImportRewriteSupport();
+ }
+ List existingImport= null;
+ if (restoreExistingImports) {
+ existingImport= new ArrayList();
+ IImportDeclaration[] imports= cu.getImports();
+ for (int i= 0; i < imports.length; i++) {
+ IImportDeclaration curr= imports[i];
+ char prefix= Flags.isStatic(curr.getFlags()) ? STATIC_PREFIX : NORMAL_PREFIX;
+ existingImport.add(prefix + curr.getElementName());
+ }
+ }
+ return new ImportRewrite(cu, null, existingImport,importRewriteExtension);
+ }
+
+ /**
+ * Creates a {@link ImportRewrite} from a an AST ({@link JavaScriptUnit}). The AST has to be created from a
+ * {@link IJavaScriptUnit}, that means {@link ASTParser#setSource(IJavaScriptUnit)} has been used when creating the
+ * AST. If restoreExistingImports
is true
, all existing imports are kept, and new imports
+ * will be inserted at best matching locations. If restoreExistingImports
is false
, the
+ * existing imports will be removed and only the newly added imports will be created.
+ *
+ * Note that this method is more efficient than using {@link #create(IJavaScriptUnit, boolean)} if an AST is already available.
+ *
+ * @param astRoot the AST root node to create the imports for
+ * @param restoreExistingImports specifies if the existing imports should be kept or removed.
+ * @return the created import rewriter.
+ * @throws IllegalArgumentException thrown when the passed AST is null or was not created from a javaScript unit.
+ */
+ public static ImportRewrite create(JavaScriptUnit astRoot, boolean restoreExistingImports) {
+ if (astRoot == null) {
+ throw new IllegalArgumentException("AST must not be null"); //$NON-NLS-1$
+ }
+ ITypeRoot typeRoot = astRoot.getTypeRoot();
+ if (!(typeRoot instanceof IJavaScriptUnit)) {
+ throw new IllegalArgumentException("AST must have been constructed from a JavaScript element"); //$NON-NLS-1$
+ }
+ ImportRewriteSupport importRewriteExtension=null;
+ InferrenceProvider[] inferenceProviders = InferrenceManager.getInstance().getInferenceProviders( (IInferenceFile)typeRoot);
+ if (inferenceProviders.length>0 && inferenceProviders[0].getRefactoringSupport()!=null)
+ {
+ RefactoringSupport refactoringSupport = inferenceProviders[0].getRefactoringSupport();
+ if (refactoringSupport!=null)
+ importRewriteExtension=refactoringSupport.getImportRewriteSupport();
+ }
+ List existingImport= null;
+ if (restoreExistingImports) {
+ existingImport= new ArrayList();
+ List imports= astRoot.imports();
+ for (int i= 0; i < imports.size(); i++) {
+ ImportDeclaration curr= (ImportDeclaration) imports.get(i);
+ StringBuffer buf= new StringBuffer();
+ buf.append(curr.isStatic() ? STATIC_PREFIX : NORMAL_PREFIX).append(curr.getName().getFullyQualifiedName());
+ if (curr.isOnDemand()) {
+ if (buf.length() > 1)
+ buf.append('.');
+ buf.append('*');
+ }
+ existingImport.add(buf.toString());
+ }
+ }
+ return new ImportRewrite((IJavaScriptUnit) typeRoot, astRoot, existingImport, importRewriteExtension);
+ }
+
+ private ImportRewrite(IJavaScriptUnit cu, JavaScriptUnit astRoot, List existingImports, ImportRewriteSupport importRewriteExtension) {
+ this.compilationUnit= cu;
+ this.astRoot= astRoot; // might be null
+ this.importRewriteExtension=importRewriteExtension;
+ if (this.importRewriteExtension!=null)
+ {
+ this.isImportMatchesType=this.importRewriteExtension.isImportMatchesType();
+ this.writeImports=true;
+ }
+ if (existingImports != null) {
+ this.existingImports= existingImports;
+ this.restoreExistingImports= !existingImports.isEmpty();
+ } else {
+ this.existingImports= new ArrayList();
+ this.restoreExistingImports= false;
+ }
+ this.filterImplicitImports= true;
+
+ this.defaultContext= new ImportRewriteContext() {
+ public int findInContext(String qualifier, String name, int kind) {
+ return findInImports(qualifier, name, kind);
+ }
+ };
+ this.addedImports= null; // Initialized on use
+ this.removedImports= null; // Initialized on use
+ this.createdImports= null;
+ this.createdStaticImports= null;
+
+ this.importOrder= CharOperation.NO_STRINGS;
+ this.importOnDemandThreshold= 99;
+ this.staticImportOnDemandThreshold= 99;
+ }
+
+
+ /**
+ * Defines the import groups and order to be used by the {@link ImportRewrite}.
+ * Imports are added to the group matching their qualified name most. The empty group name groups all imports not matching
+ * any other group. Static imports are managed in separate groups. Static import group names are prefixed with a '#' character.
+ * @param order A list of strings defining the import groups. A group name must be a valid package name or empty. If can be
+ * prefixed by the '#' character for static import groups
+ */
+ public void setImportOrder(String[] order) {
+ if (order == null)
+ throw new IllegalArgumentException("Order must not be null"); //$NON-NLS-1$
+ this.importOrder= order;
+ }
+
+ /**
+ * Sets the on-demand import threshold for normal (non-static) imports.
+ * This threshold defines the number of imports that need to be in a group to use
+ * a on-demand (star) import declaration instead.
+ *
+ * @param threshold a positive number defining the on-demand import threshold
+ * for normal (non-static) imports.
+ * @throws IllegalArgumentException a {@link IllegalArgumentException} is thrown
+ * if the number is not positive.
+ */
+ public void setOnDemandImportThreshold(int threshold) {
+ if (threshold <= 0)
+ throw new IllegalArgumentException("Threshold must be positive."); //$NON-NLS-1$
+ this.importOnDemandThreshold= threshold;
+ }
+
+ /**
+ * Sets the on-demand import threshold for static imports.
+ * This threshold defines the number of imports that need to be in a group to use
+ * a on-demand (star) import declaration instead.
+ *
+ * @param threshold a positive number defining the on-demand import threshold
+ * for normal (non-static) imports.
+ * @throws IllegalArgumentException a {@link IllegalArgumentException} is thrown
+ * if the number is not positive.
+ */
+ public void setStaticOnDemandImportThreshold(int threshold) {
+ if (threshold <= 0)
+ throw new IllegalArgumentException("Threshold must be positive."); //$NON-NLS-1$
+ this.staticImportOnDemandThreshold= threshold;
+ }
+
+ /**
+ * The javaScript unit for which this import rewrite was created for.
+ * @return the javaScript unit for which this import rewrite was created for.
+ */
+ public IJavaScriptUnit getCompilationUnit() {
+ return this.compilationUnit;
+ }
+
+ /**
+ * Returns the default rewrite context that only knows about the imported types. Clients
+ * can write their own context and use the default context for the default behavior.
+ * @return the default import rewrite context.
+ */
+ public ImportRewriteContext getDefaultImportRewriteContext() {
+ return this.defaultContext;
+ }
+
+ /**
+ * Specifies that implicit imports (types in default package, package java.lang
or
+ * in the same package as the rewrite javaScript unit should not be created except if necessary
+ * to resolve an on-demand import conflict. The filter is enabled by default.
+ * @param filterImplicitImports if set, implicit imports will be filtered.
+ */
+ public void setFilterImplicitImports(boolean filterImplicitImports) {
+ this.filterImplicitImports= filterImplicitImports;
+ }
+
+ private static int compareImport(char prefix, String qualifier, String name, String curr) {
+ if (curr.charAt(0) != prefix || !curr.endsWith(name)) {
+ return ImportRewriteContext.RES_NAME_UNKNOWN;
+ }
+
+ curr= curr.substring(1); // remove the prefix
+
+ if (curr.length() == name.length()) {
+ if (qualifier.length() == 0) {
+ return ImportRewriteContext.RES_NAME_FOUND;
+ }
+ return ImportRewriteContext.RES_NAME_CONFLICT;
+ }
+ // at this place: curr.length > name.length
+
+ int dotPos= curr.length() - name.length() - 1;
+ if (curr.charAt(dotPos) != '.') {
+ return ImportRewriteContext.RES_NAME_UNKNOWN;
+ }
+ if (qualifier.length() != dotPos || !curr.startsWith(qualifier)) {
+ return ImportRewriteContext.RES_NAME_CONFLICT;
+ }
+ return ImportRewriteContext.RES_NAME_FOUND;
+ }
+
+ /**
+ * Not API, package visibility as accessed from an anonymous type
+ */
+ /* package */ final int findInImports(String qualifier, String name, int kind) {
+ boolean allowAmbiguity= (kind == ImportRewriteContext.KIND_STATIC_METHOD) || (name.length() == 1 && name.charAt(0) == '*');
+ List imports= this.existingImports;
+ char prefix= (kind == ImportRewriteContext.KIND_TYPE) ? NORMAL_PREFIX : STATIC_PREFIX;
+
+ for (int i= imports.size() - 1; i >= 0 ; i--) {
+ String curr= (String) imports.get(i);
+ int res= compareImport(prefix, qualifier, name, curr);
+ if (res != ImportRewriteContext.RES_NAME_UNKNOWN) {
+ if (!allowAmbiguity || res == ImportRewriteContext.RES_NAME_FOUND) {
+ return res;
+ }
+ }
+ }
+ return ImportRewriteContext.RES_NAME_UNKNOWN;
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} node that can be used
+ * in the code as a reference to the type. The type binding can be an array binding or type variable.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param typeSig the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImportFromSignature(String typeSig, AST ast) {
+ return addImportFromSignature(typeSig, ast, this.defaultContext);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} node that can be used
+ * in the code as a reference to the type. The type binding can be an array binding or type variable.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param typeSig the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @param context an optional context that knows about types visible in the current scope or null
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImportFromSignature(String typeSig, AST ast, ImportRewriteContext context) {
+ if (typeSig == null || typeSig.length() == 0) {
+ throw new IllegalArgumentException("Invalid type signature: empty or null"); //$NON-NLS-1$
+ }
+ int sigKind= Signature.getTypeSignatureKind(typeSig);
+ switch (sigKind) {
+ case Signature.BASE_TYPE_SIGNATURE:
+ return ast.newPrimitiveType(PrimitiveType.toCode(Signature.toString(typeSig)));
+ case Signature.ARRAY_TYPE_SIGNATURE:
+ Type elementType= addImportFromSignature(Signature.getElementType(typeSig), ast, context);
+ return ast.newArrayType(elementType, Signature.getArrayCount(typeSig));
+ case Signature.CLASS_TYPE_SIGNATURE:
+ String erasureName= Signature.toString(typeSig);
+ if (typeSig.charAt(0) == Signature.C_RESOLVED) {
+ erasureName= internalAddImport(erasureName, erasureName, context);
+ }
+ Type baseType= ast.newSimpleType(ast.newName(erasureName));
+ return baseType;
+ default:
+ throw new IllegalArgumentException("Unknown type signature kind: " + typeSig); //$NON-NLS-1$
+ }
+ }
+
+
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can be an array binding or type variable.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param binding the signature of the type to be added.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(ITypeBinding binding) {
+ return addImport(binding, this.defaultContext);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can be an array binding or type variable.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param binding the signature of the type to be added.
+ * @param context an optional context that knows about types visible in the current scope or null
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(ITypeBinding binding, ImportRewriteContext context) {
+ if (binding.isPrimitive()) {
+ return binding.getName();
+ }
+
+ ITypeBinding normalizedBinding= normalizeTypeBinding(binding);
+ if (normalizedBinding == null) {
+ return "invalid"; //$NON-NLS-1$
+ }
+
+ if (normalizedBinding.isArray()) {
+ StringBuffer res= new StringBuffer(addImport(normalizedBinding.getElementType(), context));
+ for (int i= normalizedBinding.getDimensions(); i > 0; i--) {
+ res.append("[]"); //$NON-NLS-1$
+ }
+ return res.toString();
+ }
+
+ String qualifiedName= getRawQualifiedName(normalizedBinding);
+ if (qualifiedName.length() > 0) {
+ String str= internalAddImport(qualifiedName, qualifiedName, context);
+ return str;
+ }
+ return getRawName(normalizedBinding);
+ }
+
+ private static ITypeBinding normalizeTypeBinding(ITypeBinding binding) {
+ if (binding != null && !binding.isNullType() && !"void".equals(binding.getName())) { //$NON-NLS-1$
+ if (binding.isAnonymous()) {
+ return binding.getSuperclass();
+ }
+ return binding;
+ }
+ return null;
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
+ * in the code. The type binding can be an array binding or type variable.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param binding the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImport(ITypeBinding binding, AST ast) {
+ return addImport(binding, ast, this.defaultContext);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
+ * in the code. The type binding can be an array binding or type variable.
+ * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
+ * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param binding the signature of the type to be added.
+ * @param ast the AST to create the returned type for.
+ * @param context an optional context that knows about types visible in the current scope or null
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public Type addImport(ITypeBinding binding, AST ast, ImportRewriteContext context) {
+ if (binding.isPrimitive() || binding.isRecovered()) {
+ return ast.newPrimitiveType(PrimitiveType.toCode(binding.getName()));
+ }
+
+ ITypeBinding normalizedBinding= normalizeTypeBinding(binding);
+ if (normalizedBinding == null) {
+ return ast.newSimpleType(ast.newSimpleName("invalid")); //$NON-NLS-1$
+ }
+
+ if (normalizedBinding.isArray()) {
+ Type elementType= addImport(normalizedBinding.getElementType(), ast, context);
+ return ast.newArrayType(elementType, normalizedBinding.getDimensions());
+ }
+
+ String qualifiedName= getRawQualifiedName(normalizedBinding);
+ if (qualifiedName.length() > 0) {
+ String res= internalAddImport(qualifiedName, qualifiedName, context);
+
+ return ast.newSimpleType(ast.newName(res));
+ }
+ return ast.newSimpleType(ast.newName(getRawName(normalizedBinding)));
+ }
+
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can only be an array or non-generic type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param qualifiedTypeName the qualified type name of the type to be added
+ * @param context an optional context that knows about types visible in the current scope or null
+ * to use the default context only using the available imports.
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(String qualifiedTypeName, String packageName, ImportRewriteContext context) {
+ if (packageName==null)
+ packageName=qualifiedTypeName;
+ if (JavaScriptCore.IS_ECMASCRIPT4) {
+ int angleBracketOffset = qualifiedTypeName.indexOf('<');
+ if (angleBracketOffset != -1) {
+ return internalAddImport(qualifiedTypeName.substring(0,
+ angleBracketOffset), packageName, context)
+ + qualifiedTypeName.substring(angleBracketOffset);
+ }
+ int bracketOffset = qualifiedTypeName.indexOf('[');
+ if (bracketOffset != -1) {
+ return internalAddImport(qualifiedTypeName.substring(0,
+ bracketOffset), packageName, context)
+ + qualifiedTypeName.substring(bracketOffset);
+ }
+ }
+ return internalAddImport(qualifiedTypeName, packageName, context);
+ }
+
+ /**
+ * Adds a new import to the rewriter's record and returns a type reference that can be used
+ * in the code. The type binding can only be an array or non-generic type.
+ *
+ * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param qualifiedTypeName the qualified type name of the type to be added
+ * @return returns a type to which the type binding can be assigned to. The returned type contains is unqualified
+ * when an import could be added or was already known. It is fully qualified, if an import conflict prevented the import.
+ */
+ public String addImport(String qualifiedTypeName) {
+ return addImport(qualifiedTypeName, qualifiedTypeName, this.defaultContext);
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ *
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param binding The binding of the static field or method to be added.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ * @throws IllegalArgumentException an {@link IllegalArgumentException} is thrown if the binding is not a static field
+ * or method.
+ */
+ public String addStaticImport(IBinding binding) {
+ return addStaticImport(binding, this.defaultContext);
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ *
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param binding The binding of the static field or method to be added.
+ * @param context an optional context that knows about members visible in the current scope or null
+ * to use the default context only using the available imports.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ * @throws IllegalArgumentException an {@link IllegalArgumentException} is thrown if the binding is not a static field
+ * or method.
+ */
+ public String addStaticImport(IBinding binding, ImportRewriteContext context) {
+ if (Modifier.isStatic(binding.getModifiers())) {
+ if (binding instanceof IVariableBinding) {
+ IVariableBinding variableBinding= (IVariableBinding) binding;
+ if (variableBinding.isField()) {
+ ITypeBinding declaringType= variableBinding.getDeclaringClass();
+ return addStaticImport(getRawQualifiedName(declaringType), binding.getName(), true, context);
+ }
+ } else if (binding instanceof IFunctionBinding) {
+ ITypeBinding declaringType= ((IFunctionBinding) binding).getDeclaringClass();
+ return addStaticImport(getRawQualifiedName(declaringType), binding.getName(), false, context);
+ }
+ }
+ throw new IllegalArgumentException("Binding must be a static field or method."); //$NON-NLS-1$
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ *
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param declaringTypeName The qualified name of the static's member declaring type
+ * @param simpleName the simple name of the member; either a field or a method name.
+ * @param isField true
specifies that the member is a field, false
if it is a
+ * method.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ */
+ public String addStaticImport(String declaringTypeName, String simpleName, boolean isField) {
+ return addStaticImport(declaringTypeName, simpleName, isField, this.defaultContext);
+ }
+
+ /**
+ * Adds a new static import to the rewriter's record and returns a reference that can be used in the code. The reference will
+ * be fully qualified if an import conflict prevented the import or unqualified if the import succeeded or was already
+ * existing.
+ *
+ * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
+ *
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been added.
+ *
+ * @param declaringTypeName The qualified name of the static's member declaring type
+ * @param simpleName the simple name of the member; either a field or a method name.
+ * @param isField true
specifies that the member is a field, false
if it is a
+ * method.
+ * @param context an optional context that knows about members visible in the current scope or null
+ * to use the default context only using the available imports.
+ * @return returns either the simple member name if the import was successful or else the qualified name if
+ * an import conflict prevented the import.
+ */
+ public String addStaticImport(String declaringTypeName, String simpleName, boolean isField, ImportRewriteContext context) {
+ if (declaringTypeName.indexOf('.') == -1) {
+ return declaringTypeName + '.' + simpleName;
+ }
+ if (context == null) {
+ context= this.defaultContext;
+ }
+ int kind= isField ? ImportRewriteContext.KIND_STATIC_FIELD : ImportRewriteContext.KIND_STATIC_METHOD;
+ int res= context.findInContext(declaringTypeName, simpleName, kind);
+ if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
+ return declaringTypeName + '.' + simpleName;
+ }
+ if (res == ImportRewriteContext.RES_NAME_UNKNOWN) {
+ addEntry(STATIC_PREFIX + declaringTypeName + '.' + simpleName);
+ }
+ return simpleName;
+ }
+
+ private String internalAddImport(String fullTypeName, String packageName,ImportRewriteContext context) {
+ String importName=(this.isImportMatchesType)? fullTypeName : packageName;
+
+ int idx= importName.lastIndexOf('.');
+ String typeContainerName, typeName;
+ if (idx != -1) {
+ typeContainerName= importName.substring(0, idx);
+ typeName= importName.substring(idx + 1);
+ } else {
+ typeContainerName= ""; //$NON-NLS-1$
+ typeName= importName;
+ }
+
+ if (typeContainerName.length() == 0 && PrimitiveType.toCode(typeName) != null) {
+ return fullTypeName;
+ }
+
+ if (context == null)
+ context= this.defaultContext;
+
+ int res= context.findInContext(typeContainerName, typeName, ImportRewriteContext.KIND_TYPE);
+ if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
+ return fullTypeName;
+ }
+ if (res == ImportRewriteContext.RES_NAME_UNKNOWN) {
+ addEntry(NORMAL_PREFIX + importName);
+ }
+ return fullTypeName;
+ }
+
+ private void addEntry(String entry) {
+ this.existingImports.add(entry);
+
+ if (this.removedImports != null) {
+ if (this.removedImports.remove(entry)) {
+ return;
+ }
+ }
+
+ if (this.addedImports == null) {
+ this.addedImports= new ArrayList();
+ }
+ this.addedImports.add(entry);
+ }
+
+ private boolean removeEntry(String entry) {
+ if (this.existingImports.remove(entry)) {
+ if (this.addedImports != null) {
+ if (this.addedImports.remove(entry)) {
+ return true;
+ }
+ }
+ if (this.removedImports == null) {
+ this.removedImports= new ArrayList();
+ }
+ this.removedImports.add(entry);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Records to remove a import. No remove is recorded if no such import exists or if such an import is recorded
+ * to be added. In that case the record of the addition is discarded.
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that an import has been removed.
+ *
+ * @param qualifiedName The import name to remove.
+ * @return true
is returned of an import of the given name could be found.
+ */
+ public boolean removeImport(String qualifiedName) {
+ return removeEntry(NORMAL_PREFIX + qualifiedName);
+ }
+
+ /**
+ * Records to remove a static import. No remove is recorded if no such import exists or if such an import is recorded
+ * to be added. In that case the record of the addition is discarded.
+ *
+ * The content of the javaScript unit itself is actually not modified
+ * in any way by this method; rather, the rewriter just records that a new import has been removed.
+ *
+ * @param qualifiedName The import name to remove.
+ * @return true
is returned of an import of the given name could be found.
+ */
+ public boolean removeStaticImport(String qualifiedName) {
+ return removeEntry(STATIC_PREFIX + qualifiedName);
+ }
+
+ private static String getRawName(ITypeBinding normalizedBinding) {
+ return normalizedBinding.getTypeDeclaration().getName();
+ }
+
+ private static String getRawQualifiedName(ITypeBinding normalizedBinding) {
+ return normalizedBinding.getTypeDeclaration().getQualifiedName();
+ }
+
+
+ /**
+ * Converts all modifications recorded by this rewriter into an object representing the corresponding text
+ * edits to the source code of the rewrite's javaScript unit. The javaScript unit itself is not modified.
+ *
+ * Calling this methods does not discard the modifications on record. Subsequence modifications are added
+ * to the ones already on record. If this method is called again later, the resulting text edit object will accurately
+ * reflect the net cumulative affect of all those changes.
+ *
+ * @param monitor the progress monitor or null
+ * @return text edit object describing the changes to the document corresponding to the changes
+ * recorded by this rewriter
+ * @throws CoreException the exception is thrown if the rewrite fails.
+ */
+ public final TextEdit rewriteImports(IProgressMonitor monitor) throws CoreException {
+ if (monitor == null) {
+ monitor= new NullProgressMonitor();
+ }
+
+ try {
+ monitor.beginTask(Messages.bind(Messages.importRewrite_processDescription), 2);
+ if (!hasRecordedChanges()) {
+ this.createdImports= CharOperation.NO_STRINGS;
+ this.createdStaticImports= CharOperation.NO_STRINGS;
+ return new MultiTextEdit();
+ }
+
+ JavaScriptUnit usedAstRoot= this.astRoot;
+ if (usedAstRoot == null) {
+ ASTParser parser= ASTParser.newParser(AST.JLS3);
+ parser.setSource(this.compilationUnit);
+ parser.setFocalPosition(0); // reduced AST
+ parser.setResolveBindings(false);
+ usedAstRoot= (JavaScriptUnit) parser.createAST(new SubProgressMonitor(monitor, 1));
+ }
+
+ ImportRewriteAnalyzer computer= new ImportRewriteAnalyzer(this.compilationUnit, usedAstRoot, this.importOrder,
+ this.importOnDemandThreshold, this.staticImportOnDemandThreshold, this.restoreExistingImports,
+ this.importRewriteExtension);
+ computer.setFilterImplicitImports(this.filterImplicitImports);
+
+ if (this.addedImports != null) {
+ for (int i= 0; i < this.addedImports.size(); i++) {
+ String curr= (String) this.addedImports.get(i);
+ computer.addImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0));
+ }
+ }
+
+ if (this.removedImports != null) {
+ for (int i= 0; i < this.removedImports.size(); i++) {
+ String curr= (String) this.removedImports.get(i);
+ computer.removeImport(curr.substring(1), STATIC_PREFIX == curr.charAt(0));
+ }
+ }
+
+ TextEdit result= computer.getResultingEdits(new SubProgressMonitor(monitor, 1));
+ this.createdImports= computer.getCreatedImports();
+ this.createdStaticImports= computer.getCreatedStaticImports();
+ return result;
+ } finally {
+ monitor.done();
+ }
+ }
+
+ /**
+ * Returns all new non-static imports created by the last invocation of {@link #rewriteImports(IProgressMonitor)}
+ * or null
if these methods have not been called yet.
+ *
+ * Note that this list doesn't need to be the same as the added imports (see {@link #getAddedImports()}) as
+ * implicit imports are not created and some imports are represented by on-demand imports instead.
+ *
+ * @return the created imports
+ */
+ public String[] getCreatedImports() {
+ return this.createdImports;
+ }
+
+ /**
+ * Returns all new static imports created by the last invocation of {@link #rewriteImports(IProgressMonitor)}
+ * or null
if these methods have not been called yet.
+ *
+ * Note that this list doesn't need to be the same as the added static imports ({@link #getAddedStaticImports()}) as
+ * implicit imports are not created and some imports are represented by on-demand imports instead.
+ *
true
if imports have been recorded to be added or removed.
+ * @return boolean returns if any changes to imports have been recorded.
+ */
+ public boolean hasRecordedChanges() {
+ if (!writeImports)
+ return false;
+ return !this.restoreExistingImports ||
+ (this.addedImports != null && !this.addedImports.isEmpty()) ||
+ (this.removedImports != null && !this.removedImports.isEmpty());
+ }
+
+
+ private static String[] filterFromList(List imports, char prefix) {
+ if (imports == null) {
+ return CharOperation.NO_STRINGS;
+ }
+ ArrayList res= new ArrayList();
+ for (int i= 0; i < imports.size(); i++) {
+ String curr= (String) imports.get(i);
+ if (prefix == curr.charAt(0)) {
+ res.add(curr.substring(1));
+ }
+ }
+ return (String[]) res.toArray(new String[res.size()]);
+ }
+
+ public boolean isImportMatchesType() {
+ return isImportMatchesType;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ListRewrite.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ListRewrite.java
new file mode 100644
index 0000000..9cc4edf
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/ListRewrite.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom.rewrite;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.text.edits.TextEditGroup;
+import org.eclipse.wst.jsdt.core.dom.ASTNode;
+import org.eclipse.wst.jsdt.core.dom.Block;
+import org.eclipse.wst.jsdt.core.dom.FieldDeclaration;
+import org.eclipse.wst.jsdt.core.dom.Statement;
+import org.eclipse.wst.jsdt.core.dom.StructuralPropertyDescriptor;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.ListRewriteEvent;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.NodeInfoStore;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEvent;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore;
+import org.eclipse.wst.jsdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+
+/**
+ * For describing manipulations to a child list property of an AST node.
+ *
+ * This class is not intended to be subclassed.
+ *
+ * @see ASTRewrite#getListRewrite(ASTNode, org.eclipse.wst.jsdt.core.dom.ChildListPropertyDescriptor)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class ListRewrite {
+
+ private ASTNode parent;
+ private StructuralPropertyDescriptor childProperty;
+ private ASTRewrite rewriter;
+
+
+ /* package*/ ListRewrite(ASTRewrite rewriter, ASTNode parent, StructuralPropertyDescriptor childProperty) {
+ this.rewriter= rewriter;
+ this.parent= parent;
+ this.childProperty= childProperty;
+ }
+
+ private RewriteEventStore getRewriteStore() {
+ return this.rewriter.getRewriteEventStore();
+ }
+
+ private ListRewriteEvent getEvent() {
+ return getRewriteStore().getListEvent(this.parent, this.childProperty, true);
+ }
+
+ /**
+ * Returns the parent of the list for which this list rewriter was created.
+
+ * @return the node that contains the list for which this list rewriter was created
+ * @see #getLocationInParent()
+ */
+ public ASTNode getParent() {
+ return this.parent;
+ }
+
+ /**
+ * Returns the property of the parent node for which this list rewriter was created.
+ *
+ * @return the property of the parent node for which this list rewriter was created
+ * @see #getParent()
+ */
+ public StructuralPropertyDescriptor getLocationInParent() {
+ return this.childProperty;
+ }
+
+ /**
+ * Removes the given node from its parent's list property in the rewriter.
+ * The node must be contained in the list.
+ * The AST itself is not actually modified in any way; rather, the rewriter
+ * just records a note that this node has been removed from this list.
+ *
+ * @param node the node being removed
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not
+ * part of this rewriter's AST, or if the described modification is invalid
+ * (not a member of this node's original list)
+ */
+ public void remove(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ RewriteEvent event= getEvent().removeEntry(node);
+ if (editGroup != null) {
+ getRewriteStore().setEventEditGroup(event, editGroup);
+ }
+ }
+
+ /**
+ * Returns the ASTRewrite instance from which this ListRewriter has been created from.
+ * @return the parent AST Rewriter instance.
+ */
+ public ASTRewrite getASTRewrite() {
+ return this.rewriter;
+ }
+
+
+ /**
+ * Replaces the given node from its parent's list property in the rewriter.
+ * The node must be contained in the list.
+ * The replacement node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been replaced in this list.
+ *
+ * @param node the node being replaced
+ * @param replacement the replacement node, or null
if no
+ * replacement
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the replacement node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ */
+ public void replace(ASTNode node, ASTNode replacement, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ RewriteEvent event= getEvent().replaceEntry(node, replacement);
+ if (editGroup != null) {
+ getRewriteStore().setEventEditGroup(event, editGroup);
+ }
+ }
+
+ /**
+ * Inserts the given node into the list after the given element.
+ * The existing node must be in the list, either as an original or as a new
+ * node that has been inserted.
+ * The inserted node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been inserted into the list.
+ *
+ * @param node the node to insert
+ * @param element the element after which the given node is to be inserted
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node or element is null,
+ * or if the node is not part of this rewriter's AST, or if the inserted node
+ * is not a new node (or placeholder), or if element
is not a member
+ * of the list (original or new), or if the described modification is
+ * otherwise invalid
+ */
+ public void insertAfter(ASTNode node, ASTNode element, TextEditGroup editGroup) {
+ if (node == null || element == null) {
+ throw new IllegalArgumentException();
+ }
+ int index= getEvent().getIndex(element, ListRewriteEvent.BOTH);
+ if (index == -1) {
+ throw new IllegalArgumentException("Node does not exist"); //$NON-NLS-1$
+ }
+ internalInsertAt(node, index + 1, true, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list before the given element.
+ * The existing node must be in the list, either as an original or as a new
+ * node that has been inserted.
+ * The inserted node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been inserted into the list.
+ *
+ * @param node the node to insert
+ * @param element the element before which the given node is to be inserted
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node or element is null,
+ * or if the node is not part of this rewriter's AST, or if the inserted node
+ * is not a new node (or placeholder), or if element
is not a member
+ * of the list (original or new), or if the described modification is
+ * otherwise invalid
+ */
+ public void insertBefore(ASTNode node, ASTNode element, TextEditGroup editGroup) {
+ if (node == null || element == null) {
+ throw new IllegalArgumentException();
+ }
+ int index= getEvent().getIndex(element, ListRewriteEvent.BOTH);
+ if (index == -1) {
+ throw new IllegalArgumentException("Node does not exist"); //$NON-NLS-1$
+ }
+ internalInsertAt(node, index, false, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list at the start of the list.
+ * Equivalent to insertAt(node, 0, editGroup)
.
+ *
+ * @param node the node to insert
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the inserted node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ * @see #insertAt(ASTNode, int, TextEditGroup)
+ */
+ public void insertFirst(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ internalInsertAt(node, 0, false, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list at the end of the list.
+ * Equivalent to insertAt(node, -1, editGroup)
.
+ *
+ * @param node the node to insert
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the inserted node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ * @see #insertAt(ASTNode, int, TextEditGroup)
+ */
+ public void insertLast(ASTNode node, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ internalInsertAt(node, -1, true, editGroup);
+ }
+
+ /**
+ * Inserts the given node into the list at the given index.
+ * The index corresponds to a combined list of original and new nodes;
+ * removed or replaced nodes are still in the combined list.
+ * The inserted node must either be brand new (not part of the original AST)
+ * or a placeholder node (for example, one created by
+ * {@link ASTRewrite#createCopyTarget(ASTNode)},
+ * {@link ASTRewrite#createMoveTarget(ASTNode)},
+ * or {@link ASTRewrite#createStringPlaceholder(String, int)}). The AST itself
+ * is not actually modified in any way; rather, the rewriter just records
+ * a note that this node has been inserted into the list.
+ *
+ * @param node the node to insert
+ * @param index insertion index in the combined list of original and
+ * inserted nodes; -1
indicates insertion as the last element
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits, or null
if ungrouped
+ * @throws IllegalArgumentException if the node is null, or if the node is not part
+ * of this rewriter's AST, or if the inserted node is not a new node (or
+ * placeholder), or if the described modification is otherwise invalid
+ * (not a member of this node's original list)
+ * @throws IndexOutOfBoundsException if the index is negative and not -1,
+ * or if it is larger than the size of the combined list
+ */
+ public void insertAt(ASTNode node, int index, TextEditGroup editGroup) {
+ if (node == null) {
+ throw new IllegalArgumentException();
+ }
+ internalInsertAt(node, index, isInsertBoundToPreviousByDefault(node), editGroup);
+ }
+
+ private void internalInsertAt(ASTNode node, int index, boolean boundToPrevious, TextEditGroup editGroup) {
+ RewriteEvent event= getEvent().insert(node, index);
+ if (boundToPrevious) {
+ getRewriteStore().setInsertBoundToPrevious(node);
+ }
+ if (editGroup != null) {
+ getRewriteStore().setEventEditGroup(event, editGroup);
+ }
+ }
+
+
+ private ASTNode createTargetNode(ASTNode first, ASTNode last, boolean isMove, ASTNode replacingNode, TextEditGroup editGroup) {
+ if (first == null || last == null) {
+ throw new IllegalArgumentException();
+ }
+
+ NodeInfoStore nodeStore= this.rewriter.getNodeStore();
+ ASTNode placeholder= nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type
+ if (placeholder == null) {
+ throw new IllegalArgumentException("Creating a target node is not supported for nodes of type" + first.getClass().getName()); //$NON-NLS-1$
+ }
+
+ Block internalPlaceHolder= nodeStore.createCollapsePlaceholder();
+ CopySourceInfo info= getRewriteStore().createRangeCopy(this.parent, this.childProperty, first, last, isMove, internalPlaceHolder, replacingNode, editGroup);
+ nodeStore.markAsCopyTarget(placeholder, info);
+
+ return placeholder;
+ }
+
+ /**
+ * Creates and returns a placeholder node for a true copy of a range of nodes of the
+ * current list.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or last node
+ * are null
, if a node is not a child of the current list or if the first node
+ * is not before the last node. An IllegalArgumentException
is
+ * also thrown if the copied range is overlapping with an other moved or copied range.
+ */
+ public final ASTNode createCopyTarget(ASTNode first, ASTNode last) {
+ if (first == last) {
+ return this.rewriter.createCopyTarget(first);
+ } else {
+ return createTargetNode(first, last, false, null, null);
+ }
+ }
+
+ /**
+ * Creates and returns a placeholder node for a move of a range of nodes of the
+ * current list.
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or last node
+ * are null
, if a node is not a child of the current list or if the first node
+ * is not before the last node. An IllegalArgumentException
is
+ * also thrown if the moved range is overlapping with an other moved or copied range.
+ *
+ */
+ public final ASTNode createMoveTarget(ASTNode first, ASTNode last) {
+ return createMoveTarget(first, last, null, null);
+ }
+
+ /**
+ * Creates and returns a placeholder node for a move of a range of nodes of the
+ * current list. The moved nodes can optionally be replaced by a specified node.
+ *
+ * The placeholder node can either be inserted as new or used to replace an
+ * existing node. When the document is rewritten, a copy of the source code
+ * for the given node range is inserted into the output document at the position
+ * corresponding to the placeholder (indentation is adjusted).
+ *
+ * @param first the node that starts the range
+ * @param last the node that ends the range
+ * @param replacingNode a node that is set at the location of the moved nodes
+ * or null
to remove all nodes
+ * @param editGroup the edit group in which to collect the corresponding
+ * text edits fro a replace, or null
if ungrouped
+ * @return the new placeholder node
+ * @throws IllegalArgumentException An exception is thrown if the first or
+ * last node are null
, if a node is not a child of the current list or
+ * if the first node is not before the last node. An IllegalArgumentException
+ *
is also thrown if the moved range is overlapping with an other moved
+ * or copied range.
+ *
+ */
+ public final ASTNode createMoveTarget(ASTNode first, ASTNode last, ASTNode replacingNode, TextEditGroup editGroup) {
+ if (first == last) {
+ replace(first, replacingNode, editGroup);
+ return this.rewriter.createMoveTarget(first);
+ } else {
+ return createTargetNode(first, last, true, replacingNode, editGroup);
+ }
+ }
+
+ /*
+ * Heuristic to decide if a inserted node is bound to previous or the next sibling.
+ */
+ private boolean isInsertBoundToPreviousByDefault(ASTNode node) {
+ return (node instanceof Statement || node instanceof FieldDeclaration);
+ }
+
+ /**
+ * Returns the original nodes in the list property managed by this
+ * rewriter. The returned list is unmodifiable.
+ *
+ * @return a list of all original nodes in the list
+ */
+ public List getOriginalList() {
+ List list= (List) getEvent().getOriginalValue();
+ return Collections.unmodifiableList(list);
+ }
+
+ /**
+ * Returns the nodes in the revised list property managed by this
+ * rewriter. The returned list is unmodifiable.
+ *
+ * @return a list of all nodes in the list taking into account
+ * all the described changes
+ */
+ public List getRewrittenList() {
+ List list= (List) getEvent().getNewValue();
+ return Collections.unmodifiableList(list);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/TargetSourceRangeComputer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/TargetSourceRangeComputer.java
new file mode 100644
index 0000000..231b5d4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/dom/rewrite/TargetSourceRangeComputer.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.dom.rewrite;
+
+import org.eclipse.wst.jsdt.core.dom.ASTNode;
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+
+/**
+ * An object for computing adjusted source ranges for AST nodes
+ * that are being replaced or deleted.
+ *
+ * For example, a refactoring like inline method may choose to replace
+ * calls to the method but leave intact any comments immediately preceding
+ * the calls. On the other hand, a refactoring like extract method may choose
+ * to extract not only the nodes for the selected code but also any
+ * comments preceding or following them.
+ *
+ *
+ * Clients should subclass if they need to influence the
+ * the source range to be affected when replacing or deleting a particular node.
+ * An instance of the subclass should be registered with
+ * {@link ASTRewrite#setTargetSourceRangeComputer(TargetSourceRangeComputer)}.
+ * During a call to {@link ASTRewrite#rewriteAST(org.eclipse.jface.text.IDocument, java.util.Map)},
+ * the {@link #computeSourceRange(ASTNode)} method on this object will be
+ * used to compute the source range for a node being deleted or replaced.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TargetSourceRangeComputer {
+
+ /**
+ * Reified source range. Instances are "value" object
+ * (cannot be modified).
+ *
+ */
+ public static final class SourceRange {
+ /**
+ * 0-based character index, or -1
+ * if no source position information is known.
+ */
+ private int startPosition;
+
+ /**
+ * (possibly 0) length, or 0
+ * if no source position information is known.
+ */
+ private int length;
+
+ /**
+ * Creates a new source range.
+ *
+ * @param startPosition the 0-based character index, or -1
+ * if no source position information is known
+ * @param length the (possibly 0) length, or 0
+ * if no source position information is known
+ */
+ public SourceRange(int startPosition, int length) {
+ this.startPosition = startPosition;
+ this.length = length;
+ }
+
+ /**
+ * Returns the start position.
+ *
+ * @return the 0-based character index, or -1
+ * if no source position information is known
+ */
+ public int getStartPosition() {
+ return this.startPosition;
+ }
+
+ /**
+ * Returns the source length.
+ *
+ * @return a (possibly 0) length, or 0
+ * if no source position information is known
+ */
+ public int getLength() {
+ return this.length;
+ }
+ }
+
+ /**
+ * Creates a new target source range computer.
+ */
+ public TargetSourceRangeComputer() {
+ // do nothing
+ }
+
+ /**
+ * Returns the target source range of the given node. Unlike
+ * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+ * the extended source range may include comments and whitespace
+ * immediately before or after the normal source range for the node.
+ *
+ * The returned source ranges must satisfy the following conditions:
+ *
+ *
- no two source ranges in an AST may be overlapping
+ * - a source range of a parent node must fully cover the source ranges of its children
+ *
+ *
+ *
+ * The default implementation uses
+ * {@link JavaScriptUnit#getExtendedStartPosition(ASTNode)}
+ * and {@link JavaScriptUnit#getExtendedLength(ASTNode)}
+ * to compute the target source range. Clients may override or
+ * extend this method to expand or contract the source range of the
+ * given node. The resulting source range must cover at least the
+ * original source range of the node.
+ *
+ *
+ * @param node the node with a known source range in the javaScript unit
+ * being rewritten
+ * @return the exact source range in the javaScript unit being rewritten
+ * that should be replaced (or deleted)
+ */
+ public SourceRange computeSourceRange(ASTNode node) {
+ ASTNode root= node.getRoot();
+ if (root instanceof JavaScriptUnit) {
+ JavaScriptUnit cu= (JavaScriptUnit) root;
+ return new SourceRange(cu.getExtendedStartPosition(node), cu.getExtendedLength(node));
+ }
+ return new SourceRange(node.getStartPosition(), node.getLength());
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/ICodeSnippetRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/ICodeSnippetRequestor.java
new file mode 100644
index 0000000..ccbbf85
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/ICodeSnippetRequestor.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.eval;
+
+import org.eclipse.core.resources.IMarker;
+
+/**
+ * A code snippet requestor implements a callback interface for installing
+ * the class files for a code snippet on the target and running it.
+ * In addition, it receives compilation problems detected during code snippet
+ * compilation.
+ *
+ * Clients may implement this interface to provide a bridge a running JavaScript VM.
+ *
+ *
+ * @see IEvaluationContext#evaluateCodeSnippet(String, ICodeSnippetRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ * @see IEvaluationContext#evaluateCodeSnippet(String, String[], String[], int[], org.eclipse.wst.jsdt.core.IType, boolean, boolean, ICodeSnippetRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface ICodeSnippetRequestor {
+
+ /**
+ * The prefix of fields that represent the local variables in a snippet
+ * class.
+ */
+ public static final String LOCAL_VAR_PREFIX = "val$";
+
+ /**
+ * The name of the field that represent 'this' in a snippet class
+ * instance.
+ */
+ public static final String DELEGATE_THIS = "val$this";
+
+ /**
+ * The name of the instance method in the snippet class that runs the code
+ * snippet.
+ */
+ public static final String RUN_METHOD = "run";
+
+ /**
+ * The name of the field (of type java.lang.Object
) on the code
+ * snippet instance that contains the returned value.
+ */
+ public static final String RESULT_VALUE_FIELD = "resultValue";
+
+ /**
+ * The field of type java.lang.Class on the code snippet instance that contains the type of the returned value.
+ * The name of the field (of type java.lang.Class
) on the code
+ * snippet instance that contains the runtime type of the returned value.
+ */
+ public static final String RESULT_TYPE_FIELD = "resultType";
+
+ /*
+ * REPORTING A PROBLEM OF COMPILATION IN THE CODE SNIPPET
+ */
+
+ /**
+ * Indicates a compilation problem related to a global variable.
+ *
+ * Note: if the problem is on the type of the variable, the marker
+ * source line number is -1; if the name of the variable, line number is 0;
+ * otherwise, the marker source line number is relative to the initializer
+ * code.
+ *
+ *
+ * @see #acceptProblem(IMarker, String, int)
+ */
+ public static final int VARIABLE = 1;
+
+ /**
+ * Indicates a compilation problem related to a code snippet.
+ *
+ * @see #acceptProblem(IMarker, String, int)
+ */
+ public static final int CODE_SNIPPET = 2;
+
+ /**
+ * Indicates a compilation problem related to an import declaration.
+ *
+ * @see #acceptProblem(IMarker, String, int)
+ */
+ public static final int IMPORT = 3;
+
+ /**
+ * Indicates a compilation problem related to a package declaration.
+ *
+ * @see #acceptProblem(IMarker, String, int)
+ */
+ public static final int PACKAGE = 4;
+
+ /**
+ * Indicates an internal problem.
+ *
+ * @see #acceptProblem(IMarker, String, int)
+ */
+ public static final int INTERNAL = 5;
+/**
+ * Sends the given class files to the target and loads them. If the given
+ * class name is not null
, run the code snippet with this class
+ * name. Returns whether the code snippet could be deployed. Note it must
+ * return true
even if running the code snippet threw an exception.
+ *
+ * The details of sending and loading the class files are left up to
+ * implementations.
+ *
+ *
+ * To run a code snippet, an implementation should create a new instance of
+ * the given code snippet class and call (directly or using another means) its
+ * RUN_METHOD
.
+ *
+ *
+ * Also before the call, the implementation should copy the values of the local
+ * variables (if any) into the corresponding fields of the code snippet instance.
+ * A field name is formed of LOCAL_VAR_PREFIX
+ * preceded the name of the local variable. For example, the field name for
+ * local variable "myLocal"
is "val$myLocal"
(assuming the
+ * value of LOCAL_VAR_PREFIX
is "val$"). In the
+ * same way, the implementation should copy the value of the 'this' object into the
+ * field called DELEGATE_THIS
.
+ *
+ *
+ * After calling the RUN_METHOD
, the values of the local
+ * variables may have been modified. The implementation must copy the
+ * values of the fields back into the local variables.
+ *
+ *
+ * Finally, the overall value returned by the code snippet can be retrieved
+ * from the special field RESULT_VALUE_FIELD
+ * on the code snippet instance.
+ * The Class
that is the runtime type of the returned value can be
+ * retrieved from the special field RESULT_TYPE_FIELD
.
+ *
+ *
+ * @param classFileBytes the list of class file bytes
+ * @param classFileCompoundNames the corresponding list of class file type
+ * compound names (example of a compound name: {"java", "lang", "Object"})
+ * @param codeSnippetClassName name of the actual class to instantiate and run,
+ * or null
if none
+ * @return true
if the code snippet was successfully deployed
+ */
+public boolean acceptClassFiles(byte[][] classFileBytes, String[][] classFileCompoundNames, String codeSnippetClassName);
+/**
+ * Notifies of an evaluation problem.
+ * Problems can arise for source of the following kinds:
+ *
+ *
+ * - global variable (
VARIABLE
) - fragment source is name of
+ * variable
+ * - code snippet (
CODE_SNIPPET
) - fragment source is code
+ * snippet
+ * - import declaration (
IMPORT
) - fragment source is
+ * import
+ * - package declaration (
PACKAGE
) - fragment source is
+ * package declaration
+ * - other (
INTERNAL
) - no fragment source is involved, internal error occurred.
+ *
+ *
+ * @param problemMarker the problem marker (cannot be null)
+ * @param fragmentSource the fragment source
+ * @param fragmentKind the kind of source fragment; one of:
+ * VARIABLE
, CODE_SNIPPET
, IMPORT
,
+ * PACKAGE
, or INTERNAL
+ */
+public void acceptProblem(IMarker problemMarker, String fragmentSource, int fragmentKind);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/IEvaluationContext.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/IEvaluationContext.java
new file mode 100644
index 0000000..e1e4254
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/IEvaluationContext.java
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.eval;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.jsdt.core.CompletionRequestor;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
+
+/**
+ * An evaluation context supports evaluating code snippets.
+ *
+ * A code snippet is pretty much any valid piece of JavaScript code that could be
+ * pasted into the body of a method and compiled. However, there are two
+ * areas where the rules are slightly more liberal.
+ *
+ * First, a code snippet can return heterogeneous types. Inside the same code
+ * snippet an int
could be returned on one line, and a
+ * String
on the next, etc. For example, the following would be
+ * considered a valid code snippet:
+ *
+ *
+ * char c = '3';
+ * switch (c) {
+ * case '1': return 1;
+ * case '2': return '2';
+ * case '3': return "3";
+ * default: return null;
+ * }
+ *
+ *
+ *
+ *
+ * Second, if the last statement is only an expression, the return
+ * keyword is implied. For example, the following returns false
:
+ *
+ *
+ * int i = 1;
+ * i == 2
+ *
+ *
+ *
+ *
+ * Global variables are an additional feature of evaluation contexts. Within an
+ * evaluation context, global variables maintain their value across evaluations.
+ * These variables are particularly useful for storing the result of an
+ * evaluation for use in subsequent evaluations.
+ *
+ *
+ * The evaluation context remembers the name of the package in which code
+ * snippets are run. The user can set this to any package, thereby gaining
+ * access to types that are normally only visible within that package.
+ *
+ *
+ * Finally, the evaluation context remembers a list of import declarations. The
+ * user can import any packages and types so that the code snippets may refer
+ * to types by their shorter simple names.
+ *
+ *
+ * Example of use:
+ *
+ *
+ * IJavaScriptProject project = getJavaProject();
+ * IEvaluationContext context = project.newEvaluationContext();
+ * String codeSnippet = "int i= 0; i++";
+ * ICodeSnippetRequestor requestor = ...;
+ * context.evaluateCodeSnippet(codeSnippet, requestor, progressMonitor);
+ *
+ *
+ *
+ *
+ * This interface is not intended to be implemented by clients.
+ * IJavaScriptProject.newEvaluationContext
can be used to obtain an
+ * instance.
+ *
+ *
+ * @see IJavaScriptProject#newEvaluationContext()
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IEvaluationContext {
+ /**
+ * Returns the global variables declared in this evaluation context.
+ * The variables are maintained in the order they are created in.
+ *
+ * @return the list of global variables
+ */
+ public IGlobalVariable[] allVariables();
+
+ /**
+ * Performs a code completion at the given position in the given code snippet,
+ * reporting results to the given completion requestor.
+ *
+ * Note that code completion does not involve evaluation.
+ *
+ *
+ * @param codeSnippet the code snippet to complete in
+ * @param position the character position in the code snippet to complete at,
+ * or -1 indicating the beginning of the snippet
+ * @param requestor the code completion requestor capable of accepting all
+ * possible types of completions
+ * @exception JavaScriptModelException if code completion could not be performed. Reasons include:
+ *
+ * - The position specified is less than -1 or is greater than the snippet's
+ * length (INDEX_OUT_OF_BOUNDS)
+ *
+ *
+ */
+ public void codeComplete(
+ String codeSnippet,
+ int position,
+ CompletionRequestor requestor)
+ throws JavaScriptModelException;
+ /**
+ * Performs a code completion at the given position in the given code snippet,
+ * reporting results to the given completion requestor.
+ * It considers types in the working copies with the given owner first. In other words,
+ * the owner's working copies will take precedence over their original javascript unit s
+ * in the workspace.
+ *
+ * Note that if a working copy is empty, it will be as if the original compilation
+ * unit had been deleted.
+ *
+ *
+ * Note that code completion does not involve evaluation.
+ *
+ *
+ * @param codeSnippet the code snippet to complete in
+ * @param position the character position in the code snippet to complete at,
+ * or -1 indicating the beginning of the snippet
+ * @param requestor the code completion requestor capable of accepting all
+ * possible types of completions
+ * @param owner the owner of working copies that take precedence over their original javascript unit s
+ * @exception JavaScriptModelException if code completion could not be performed. Reasons include:
+ *
+ * - The position specified is less than -1 or is greater than the snippet's
+ * length (INDEX_OUT_OF_BOUNDS)
+ *
+ *
+ */
+ public void codeComplete(
+ String codeSnippet,
+ int position,
+ CompletionRequestor requestor,
+ WorkingCopyOwner owner)
+ throws JavaScriptModelException;
+ /**
+ * Resolves and returns a collection of JavaScript elements corresponding to the source
+ * code at the given positions in the given code snippet.
+ *
+ * Note that code select does not involve evaluation, and problems are never
+ * reported.
+ *
+ *
+ * @param codeSnippet the code snippet to resolve in
+ * @param offset the position in the code snippet of the first character
+ * of the code to resolve
+ * @param length the length of the selected code to resolve
+ * @return the (possibly empty) list of selection JavaScript elements
+ * @exception JavaScriptModelException if code resolve could not be performed.
+ * Reasons include:
+ *
+ * - The position specified is less than -1 or is greater than the snippet's
+ * length (INDEX_OUT_OF_BOUNDS)
+ *
+ */
+ public IJavaScriptElement[] codeSelect(String codeSnippet, int offset, int length)
+ throws JavaScriptModelException;
+ /**
+ * Resolves and returns a collection of JavaScript elements corresponding to the source
+ * code at the given positions in the given code snippet.
+ * It considers types in the working copies with the given owner first. In other words,
+ * the owner's working copies will take precedence over their original javascript unit s
+ * in the workspace.
+ *
+ * Note that if a working copy is empty, it will be as if the original compilation
+ * unit had been deleted.
+ *
+ *
+ * Note that code select does not involve evaluation, and problems are never
+ * reported.
+ *
+ *
+ * @param codeSnippet the code snippet to resolve in
+ * @param offset the position in the code snippet of the first character
+ * of the code to resolve
+ * @param length the length of the selected code to resolve
+ * @param owner the owner of working copies that take precedence over their original javascript unit s
+ * @return the (possibly empty) list of selection JavaScript elements
+ * @exception JavaScriptModelException if code resolve could not be performed.
+ * Reasons include:
+ *
+ * - The position specified is less than -1 or is greater than the snippet's
+ * length (INDEX_OUT_OF_BOUNDS)
+ *
+ *
+ */
+ public IJavaScriptElement[] codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)
+ throws JavaScriptModelException;
+ /**
+ * Deletes the given variable from this evaluation context. Does nothing if
+ * the given variable has already been deleted.
+ *
+ * @param variable the global variable
+ */
+ public void deleteVariable(IGlobalVariable variable);
+ /**
+ * Evaluates the given code snippet in the context of a suspended thread.
+ * The code snippet is compiled along with this context's package declaration,
+ * imports, and global variables. The given requestor's
+ * acceptProblem
method is called for each compilation problem that
+ * is detected. Then the resulting class files are handed to the given
+ * requestor's acceptClassFiles
method to deploy and run.
+ *
+ * The requestor is expected to:
+ *
+ * - send the class files to the target VM,
+ *
- load them (starting with the code snippet class),
+ *
- create a new instance of the code snippet class,
+ *
- run the method
run()
of the code snippet,
+ * - retrieve the values of the local variables,
+ *
- retrieve the returned value of the code snippet
+ *
+ *
+ *
+ * This method is long-running; progress and cancellation are provided
+ * by the given progress monitor.
+ *
+ *
+ * @param codeSnippet the code snippet
+ * @param localVariableTypeNames the dot-separated fully qualified names of the types of the local variables.
+ * @param localVariableNames the names of the local variables as they are declared in the user's code.
+ * @param localVariableModifiers the modifiers of the local variables (default modifier or final modifier).
+ * @param declaringType the type in which the code snippet is evaluated.
+ * @param isStatic whether the code snippet is evaluated in a static member of the declaring type.
+ * @param isConstructorCall whether the code snippet is evaluated in a constructor of the declaring type.
+ * @param requestor the code snippet requestor
+ * @param progressMonitor a progress monitor
+ * @exception JavaScriptModelException if a runtime problem occurred or if this
+ * context's project has no build state
+ */
+ public void evaluateCodeSnippet(
+ String codeSnippet,
+ String[] localVariableTypeNames,
+ String[] localVariableNames,
+ int[] localVariableModifiers,
+ IType declaringType,
+ boolean isStatic,
+ boolean isConstructorCall,
+ ICodeSnippetRequestor requestor,
+ IProgressMonitor progressMonitor)
+ throws JavaScriptModelException;
+ /**
+ * Evaluates the given code snippet. The code snippet is
+ * compiled along with this context's package declaration, imports, and
+ * global variables. The given requestor's acceptProblem
method
+ * is called for each compilation problem that is detected. Then the resulting
+ * class files are handed to the given requestor's acceptClassFiles
+ * method to deploy and run. The requestor is also responsible for getting the
+ * result back.
+ *
+ * This method is long-running; progress and cancellation are provided
+ * by the given progress monitor.
+ *
+ *
+ * @param codeSnippet the code snippet
+ * @param requestor the code snippet requestor
+ * @param progressMonitor a progress monitor
+ * @exception JavaScriptModelException if a runtime problem occurred or if this
+ * context's project has no build state
+ */
+ public void evaluateCodeSnippet(
+ String codeSnippet,
+ ICodeSnippetRequestor requestor,
+ IProgressMonitor progressMonitor)
+ throws JavaScriptModelException;
+ /**
+ * Evaluates the given global variable. During this operation,
+ * this context's package declaration, imports, and all its declared
+ * variables are verified. The given requestor's acceptProblem
+ * method will be called for each problem that is detected.
+ *
+ * This method is long-running; progress and cancellation are provided
+ * by the given progress monitor.
+ *
+ *
+ * @param variable the global variable
+ * @param requestor the code snippet requestor
+ * @param progressMonitor a progress monitor
+ * @exception JavaScriptModelException if a runtime problem occurred or if this
+ * context's project has no build state
+ */
+ public void evaluateVariable(
+ IGlobalVariable variable,
+ ICodeSnippetRequestor requestor,
+ IProgressMonitor progressMonitor)
+ throws JavaScriptModelException;
+ /**
+ * Returns the import declarations for this evaluation context. Returns and empty
+ * list if there are no imports (the default if the imports have never been set).
+ * The syntax for the import corresponds to a fully qualified type name, or to
+ * an on-demand package name as defined by ImportDeclaration (JLS2 7.5). For
+ * example, "java.util.Hashtable"
or "java.util.*"
.
+ *
+ * @return the list of import names
+ */
+ public String[] getImports();
+ /**
+ * Returns the name of the package in which code snippets are to be compiled and
+ * run. Returns an empty string for the default package (the default if the
+ * package name has never been set). For example, "com.example.myapp"
.
+ *
+ * @return the dot-separated package name, or the empty string indicating the
+ * default package
+ */
+ public String getPackageName();
+ /**
+ * Returns the JavaScript project this evaluation context was created for.
+ *
+ * @return the JavaScript project
+ */
+ public IJavaScriptProject getProject();
+ /**
+ * Creates a new global variable with the given name, type, and initializer.
+ *
+ * The typeName
and initializer
are interpreted in
+ * the context of this context's package and import declarations.
+ *
+ *
+ * The syntax for a type name corresponds to Type in Field Declaration (JLS2 8.3).
+ *
+ *
+ * @param typeName the type name
+ * @param name the name of the global variable
+ * @param initializer the initializer expression, or null
if the
+ * variable is not initialized
+ * @return a new global variable with the given name, type, and initializer
+ */
+ public IGlobalVariable newVariable(
+ String typeName,
+ String name,
+ String initializer);
+ /**
+ * Sets the import declarations for this evaluation context. An empty
+ * list indicates there are no imports. The syntax for the import corresponds to a
+ * fully qualified type name, or to an on-demand package name as defined by
+ * ImportDeclaration (JLS2 7.5). For example, "java.util.Hashtable"
+ * or "java.util.*"
.
+ *
+ * @param imports the list of import names
+ */
+ public void setImports(String[] imports);
+ /**
+ * Sets the dot-separated name of the package in which code snippets are
+ * to be compiled and run. For example, "com.example.myapp"
.
+ *
+ * @param packageName the dot-separated package name, or the empty string
+ * indicating the default package
+ */
+ public void setPackageName(String packageName);
+ /**
+ * Validates this evaluation context's import declarations. The given requestor's
+ * acceptProblem
method is called for each problem that is detected.
+ *
+ * @param requestor the code snippet requestor
+ * @exception JavaScriptModelException if this context's project has no build state
+ */
+ public void validateImports(ICodeSnippetRequestor requestor)
+ throws JavaScriptModelException;
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/IGlobalVariable.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/IGlobalVariable.java
new file mode 100644
index 0000000..53f7b92
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/eval/IGlobalVariable.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.eval;
+
+/**
+ * A global variable declared in an evaluation context.
+ *
+ * This interface is not intended to be implemented by clients.
+ * IEvaluationContext.newVariable
can be used to obtain an instance.
+ *
+ *
+ * @see IEvaluationContext#newVariable(String, String, String)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IGlobalVariable {
+/**
+ * Returns the initializer of this global variable.
+ * The syntax for an initializer corresponds to VariableInitializer (JLS2 8.3).
+ *
+ * @return the initializer expression, or null
if this global does
+ * not have an initializer
+ */
+public String getInitializer();
+/**
+ * Returns the name of this global variable.
+ *
+ * @return the name of the global variable
+ */
+public String getName();
+/**
+ * Returns the fully qualified name of the type of this global
+ * variable, or its simple representation if it is a primitive type
+ * (int
, boolean
, etc.).
+ *
+ * The syntax for a type name corresponds to Type in Field Declaration (JLS2 8.3).
+ *
+ * @return the type name
+ */
+public String getTypeName();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/CodeFormatter.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/CodeFormatter.java
new file mode 100644
index 0000000..1889ff6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/CodeFormatter.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.formatter;
+
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+/**
+ * Specification for a generic source code formatter.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class CodeFormatter {
+
+ /**
+ * Unknown kind
+ */
+ public static final int K_UNKNOWN = 0x00;
+
+ /**
+ * Kind used to format an expression
+ */
+ public static final int K_EXPRESSION = 0x01;
+
+ /**
+ * Kind used to format a set of statements
+ */
+ public static final int K_STATEMENTS = 0x02;
+
+ /**
+ * Kind used to format a set of class body declarations
+ */
+ public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
+
+ /**
+ * Kind used to format a javascript unit
+ */
+ public static final int K_JAVASCRIPT_UNIT = 0x08;
+
+ /**
+ * Kind used to format a single-line comment
+ *
+ */
+ public static final int K_SINGLE_LINE_COMMENT = 0x10;
+ /**
+ * Kind used to format a multi-line comment
+ *
+ */
+ public static final int K_MULTI_LINE_COMMENT = 0x20;
+ /**
+ * Kind used to format a jsdoc comment
+ *
+ */
+ public static final int K_JAVA_DOC = 0x40;
+
+ /**
+ * Format source
,
+ * and returns a text edit that correspond to the difference between the given string and the formatted string.
+ * It returns null if the given string cannot be formatted.
+ *
+ * If the offset position is matching a whitespace, the result can include whitespaces. It would be up to the
+ * caller to get rid of preceeding whitespaces.
+ *
+ * @param kind Use to specify the kind of the code snippet to format. It can be any of these:
+ * K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_JAVASCRIPT_UNIT, K_UNKNOWN,
+ * K_SINGLE_LINE_COMMENT, K_MULTI_LINE_COMMENT, K_JAVA_DOC
+ * @param source the source to format
+ * @param offset the given offset to start recording the edits (inclusive).
+ * @param length the given length to stop recording the edits (exclusive).
+ * @param indentationLevel the initial indentation level, used
+ * to shift left/right the entire source fragment. An initial indentation
+ * level of zero or below has no effect.
+ * @param lineSeparator the line separator to use in formatted source,
+ * if set to null
, then the platform default one will be used.
+ * @return the text edit
+ * @throws IllegalArgumentException if offset is lower than 0, length is lower than 0 or
+ * length is greater than source length.
+ */
+ public abstract TextEdit format(int kind, String source, int offset, int length, int indentationLevel, String lineSeparator);
+
+ /**
+ * Answers the string that corresponds to the indentation to the given indentation level or an empty string
+ * if the indentation cannot be computed.
+ * This method needs to be overriden in a subclass.
+ *
+ * The default implementation returns an empty string.
+ *
+ * @param indentationLevel the given indentation level
+ * @return the string corresponding to the right indentation level
+ * @exception IllegalArgumentException if the given indentation level is lower than zero
+ *
+ */
+ public String createIndentationString(int indentationLevel) {
+ return Util.EMPTY_STRING;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/CodeFormatterApplication.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/CodeFormatterApplication.java
new file mode 100644
index 0000000..a17ce3a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/CodeFormatterApplication.java
@@ -0,0 +1,400 @@
+/*******************************************************************************
+ * Copyright (c) 2004 Ben Konrath
+ * Copyright (c) 2006 Red Hat Incorporated
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ben Konrath - initial implementation
+ * Red Hat Incorporated - improvements based on comments from JDT developers
+ * IBM Corporation - Code review and integration
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.formatter;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Properties;
+
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.jsdt.core.ToolFactory;
+import org.eclipse.wst.jsdt.internal.core.util.Util;
+
+/**
+ * Implements an Eclipse Application for org.eclipse.wst.jsdt.core.JavaCodeFormatter.
+ *
+ * There are a couple improvments that could be made: 1. Make a list of all the
+ * files first so that a file does not get formatted twice. 2. Use a text based
+ * progress monitor for output.
+ *
+ * This class is not intended to be instantiated or subclassed by clients.
+ *
+ *
+ * @author Ben Konrath
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class CodeFormatterApplication implements IApplication {
+
+ /**
+ * Deals with the messages in the properties file (cut n' pasted from a
+ * generated class).
+ */
+ private final static class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.wst.jsdt.core.formatter.messages";//$NON-NLS-1$
+
+ public static String CommandLineConfigFile;
+
+ public static String CommandLineDone;
+
+ public static String CommandLineErrorConfig;
+
+ public static String CommandLineErrorFile;
+
+ public static String CommandLineErrorFileDir;
+
+ public static String CommandLineErrorQuietVerbose;
+
+ public static String CommandLineErrorNoConfigFile;
+
+ public static String CommandLineFormatting;
+
+ public static String CommandLineStart;
+
+ public static String CommandLineUsage;
+
+ public static String ConfigFileReadingError;
+
+ public static String FormatProblem;
+
+ public static String CaughtException;
+
+ public static String ExceptionSkip;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ /**
+ * Bind the given message's substitution locations with the given string
+ * values.
+ *
+ * @param message
+ * the message to be manipulated
+ * @return the manipulated String
+ */
+ public static String bind(String message) {
+ return bind(message, null);
+ }
+
+ /**
+ * Bind the given message's substitution locations with the given string
+ * values.
+ *
+ * @param message
+ * the message to be manipulated
+ * @param binding
+ * the object to be inserted into the message
+ * @return the manipulated String
+ */
+ public static String bind(String message, Object binding) {
+ return bind(message, new Object[] {
+ binding
+ });
+ }
+
+ /**
+ * Bind the given message's substitution locations with the given string
+ * values.
+ *
+ * @param message
+ * the message to be manipulated
+ * @param binding1
+ * An object to be inserted into the message
+ * @param binding2
+ * A second object to be inserted into the message
+ * @return the manipulated String
+ */
+ public static String bind(String message, Object binding1, Object binding2) {
+ return bind(message, new Object[] {
+ binding1, binding2
+ });
+ }
+
+ /**
+ * Bind the given message's substitution locations with the given string
+ * values.
+ *
+ * @param message
+ * the message to be manipulated
+ * @param bindings
+ * An array of objects to be inserted into the message
+ * @return the manipulated String
+ */
+ public static String bind(String message, Object[] bindings) {
+ return MessageFormat.format(message, bindings);
+ }
+ }
+
+ private static final String ARG_CONFIG = "-config"; //$NON-NLS-1$
+
+ private static final String ARG_HELP = "-help"; //$NON-NLS-1$
+
+ private static final String ARG_QUIET = "-quiet"; //$NON-NLS-1$
+
+ private static final String ARG_VERBOSE = "-verbose"; //$NON-NLS-1$
+
+ private String configName;
+
+ private Map options = null;
+
+ private static final String PDE_LAUNCH = "-pdelaunch"; //$NON-NLS-1$
+
+ private boolean quiet = false;
+
+ private boolean verbose = false;
+
+ /**
+ * Display the command line usage message.
+ */
+ private void displayHelp() {
+ System.out.println(Messages.bind(Messages.CommandLineUsage));
+ }
+
+ private void displayHelp(String message) {
+ System.err.println(message);
+ System.out.println();
+ displayHelp();
+ }
+
+ /**
+ * Recursively format the JavaScript source code that is contained in the
+ * directory rooted at dir.
+ */
+ private void formatDirTree(File dir, CodeFormatter codeFormatter) {
+
+ File[] files = dir.listFiles();
+ if (files == null)
+ return;
+
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ if (file.isDirectory()) {
+ formatDirTree(file, codeFormatter);
+ } else if (Util.isJavaLikeFileName(file.getPath())) {
+ formatFile(file, codeFormatter);
+ }
+ }
+ }
+
+ /**
+ * Format the given JavaScript source file.
+ */
+ private void formatFile(File file, CodeFormatter codeFormatter) {
+ IDocument doc = new Document();
+ try {
+ // read the file
+ if (this.verbose) {
+ System.out.println(Messages.bind(Messages.CommandLineFormatting, file.getAbsolutePath()));
+ }
+ String contents = new String(org.eclipse.wst.jsdt.internal.compiler.util.Util.getFileCharContent(file, null));
+ // format the file (the meat and potatoes)
+ doc.set(contents);
+ TextEdit edit = codeFormatter.format(CodeFormatter.K_JAVASCRIPT_UNIT, contents, 0, contents.length(), 0, null);
+ if (edit != null) {
+ edit.apply(doc);
+ } else {
+ System.err.println(Messages.bind(Messages.FormatProblem, file.getAbsolutePath()));
+ return;
+ }
+
+ // write the file
+ final BufferedWriter out = new BufferedWriter(new FileWriter(file));
+ try {
+ out.write(doc.get());
+ out.flush();
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ /* ignore */
+ }
+ }
+ } catch (IOException e) {
+ String errorMessage = Messages.bind(Messages.CaughtException, "IOException", e.getLocalizedMessage()); //$NON-NLS-1$
+ Util.log(e, errorMessage);
+ System.err.println(Messages.bind(Messages.ExceptionSkip ,errorMessage));
+ } catch (BadLocationException e) {
+ String errorMessage = Messages.bind(Messages.CaughtException, "BadLocationException", e.getLocalizedMessage()); //$NON-NLS-1$
+ Util.log(e, errorMessage);
+ System.err.println(Messages.bind(Messages.ExceptionSkip ,errorMessage));
+ }
+ }
+
+ private File[] processCommandLine(String[] argsArray) {
+
+ ArrayList args = new ArrayList();
+ for (int i = 0, max = argsArray.length; i < max; i++) {
+ args.add(argsArray[i]);
+ }
+ int index = 0;
+ final int argCount = argsArray.length;
+
+ final int DEFAULT_MODE = 0;
+ final int CONFIG_MODE = 1;
+
+ int mode = DEFAULT_MODE;
+ final int INITIAL_SIZE = 1;
+ int fileCounter = 0;
+
+ File[] filesToFormat = new File[INITIAL_SIZE];
+
+ loop: while (index < argCount) {
+ String currentArg = argsArray[index++];
+
+ switch(mode) {
+ case DEFAULT_MODE :
+ if (PDE_LAUNCH.equals(currentArg)) {
+ continue loop;
+ }
+ if (ARG_HELP.equals(currentArg)) {
+ displayHelp();
+ return null;
+ }
+ if (ARG_VERBOSE.equals(currentArg)) {
+ this.verbose = true;
+ continue loop;
+ }
+ if (ARG_QUIET.equals(currentArg)) {
+ this.quiet = true;
+ continue loop;
+ }
+ if (ARG_CONFIG.equals(currentArg)) {
+ mode = CONFIG_MODE;
+ continue loop;
+ }
+ // the current arg should be a file or a directory name
+ File file = new File(currentArg);
+ if (file.exists()) {
+ if (filesToFormat.length == fileCounter) {
+ System.arraycopy(filesToFormat, 0, (filesToFormat = new File[fileCounter * 2]), 0, fileCounter);
+ }
+ filesToFormat[fileCounter++] = file;
+ } else {
+ displayHelp(Messages.bind(Messages.CommandLineErrorFile, currentArg));
+ return null;
+ }
+ break;
+ case CONFIG_MODE :
+ this.configName = currentArg;
+ this.options = readConfig(currentArg);
+ if (this.options == null) {
+ displayHelp(Messages.bind(Messages.CommandLineErrorConfig, currentArg));
+ return null;
+ }
+ mode = DEFAULT_MODE;
+ continue loop;
+ }
+ }
+
+ if (mode == CONFIG_MODE || this.options == null) {
+ displayHelp(Messages.bind(Messages.CommandLineErrorNoConfigFile));
+ return null;
+ }
+ if (this.quiet && this.verbose) {
+ displayHelp(
+ Messages.bind(
+ Messages.CommandLineErrorQuietVerbose,
+ new String[] { ARG_QUIET, ARG_VERBOSE }
+ ));
+ return null;
+ }
+ if (fileCounter == 0) {
+ displayHelp(Messages.bind(Messages.CommandLineErrorFileDir));
+ return null;
+ }
+ if (filesToFormat.length != fileCounter) {
+ System.arraycopy(filesToFormat, 0, (filesToFormat = new File[fileCounter]), 0, fileCounter);
+ }
+ return filesToFormat;
+ }
+
+ /**
+ * Return a JavaScript Properties file representing the options that are in the
+ * specified config file.
+ */
+ private Properties readConfig(String filename) {
+ BufferedInputStream stream = null;
+ try {
+ stream = new BufferedInputStream(new FileInputStream(new File(filename)));
+ final Properties formatterOptions = new Properties();
+ formatterOptions.load(stream);
+ return formatterOptions;
+ } catch (IOException e) {
+ Util.log(e, Messages.bind(Messages.ConfigFileReadingError));
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ /* ignore */
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Runs the JavaScript code formatter application
+ */
+ public Object start(IApplicationContext context) throws Exception {
+ File[] filesToFormat = processCommandLine((String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS));
+
+ if (filesToFormat == null) {
+ return IApplication.EXIT_OK;
+ }
+
+ if (!this.quiet) {
+ if (this.configName != null) {
+ System.out.println(Messages.bind(Messages.CommandLineConfigFile, this.configName));
+ }
+ System.out.println(Messages.bind(Messages.CommandLineStart));
+ }
+
+ final CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(this.options);
+ // format the list of files and/or directories
+ for (int i = 0, max = filesToFormat.length; i < max; i++) {
+ final File file = filesToFormat[i];
+ if (file.isDirectory()) {
+ formatDirTree(file, codeFormatter);
+ } else if (Util.isJavaLikeFileName(file.getPath())) {
+ formatFile(file, codeFormatter);
+ }
+ }
+ if (!this.quiet) {
+ System.out.println(Messages.bind(Messages.CommandLineDone));
+ }
+
+ return IApplication.EXIT_OK;
+ }
+ public void stop() {
+ // do nothing
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/DefaultCodeFormatterConstants.java
new file mode 100644
index 0000000..7bb65b4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -0,0 +1,3640 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.formatter;
+
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.internal.formatter.DefaultCodeFormatterOptions;
+import org.eclipse.wst.jsdt.internal.formatter.align.Alignment;
+
+/**
+ * Constants used to set up the options of the code formatter.
+ *
+ * This class is not intended to be instantiated or subclassed by clients.
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class DefaultCodeFormatterConstants {
+
+ /**
+ *
+ * FORMATTER / Value to set a brace location at the end of a line.
+ *
+ * @see #FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_OBJLIT_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_BLOCK
+ * @see #FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_SWITCH
+ * @see #FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION
+ *
+ */
+ public static final String END_OF_LINE = "end_of_line"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Value to set an option to false.
+ *
+ *
+ */
+ public static final String FALSE = "false"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to align type members of a type declaration on column
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.formatter.align_type_members_on_columns"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS = JavaScriptCore.PLUGIN_ID + ".formatter.align_type_members_on_columns"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option for alignment of arguments in allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_allocation_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of arguments in enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of arguments in explicit constructor call
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_EXPLICIT_CONSTRUCTOR_CALL = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_explicit_constructor_call"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of arguments in method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_method_invocation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of arguments in qualified allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_QUALIFIED_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_arguments_in_qualified_allocation_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of assignment
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, M_NO_ALIGNMENT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ASSIGNMENT = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_assignment"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of binary expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_BINARY_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_binary_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of compact if
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_ONE_PER_LINE, INDENT_BY_ONE)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_COMPACT_IF = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_compact_if"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of conditional expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_ONE_PER_LINE, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_conditional_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of enum constants
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_NO_SPLIT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_ENUM_CONSTANTS = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_enum_constants"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of expressions in array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_expressions_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of multiple fields
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_MULTIPLE_FIELDS = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_multiple_fields";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of parameters in constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_parameters_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of parameters in method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_parameters_in_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of selector in method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_SELECTOR_IN_METHOD_INVOCATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_selector_in_method_invocation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of superclass in type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_NEXT_SHIFTED, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_SUPERCLASS_IN_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_superclass_in_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of superinterfaces in enum declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_ENUM_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_superinterfaces_in_enum_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of superinterfaces in type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_SUPERINTERFACES_IN_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_superinterfaces_in_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of throws clause in constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_throws_clause_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option for alignment of throws clause in method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration"
+ * - possible values: values returned by createAlignmentValue(boolean, int, int)
call
+ * - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_DEFAULT)
+ *
+ * @see #createAlignmentValue(boolean, int, int)
+ *
+ */
+ public static final String FORMATTER_ALIGNMENT_FOR_THROWS_CLAUSE_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.alignment_for_throws_clause_in_method_declaration"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to add blank lines after the imports declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_AFTER_IMPORTS = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_after_imports"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines after the package declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_AFTER_PACKAGE = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_after_package"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines at the beginning of the method body
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_AT_BEGINNING_OF_METHOD_BODY = JavaScriptCore.PLUGIN_ID + ".formatter.number_of_blank_lines_at_beginning_of_method_body"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before a field declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_FIELD = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_field"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before the first class body declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_first_class_body_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before the imports declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_IMPORTS = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_imports"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before a member type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_member_type"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_METHOD = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_method"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before a new chunk
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_new_chunk"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines before the package declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BEFORE_PACKAGE = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_before_package"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines between import groups
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "1"
+ *
+ * Note: Import groups are defined once "Organize Import" operation has been executed. The code formatter itself
+ * doesn't define the import groups.
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_between_import_groups"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to add blank lines between type declarations
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_BLANK_LINES_BETWEEN_TYPE_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.blank_lines_between_type_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of an annotation type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_ANNOTATION_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_annotation_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of an anonymous type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_anonymous_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of an object literal initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_OBJLIT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_objlit_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of a block
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_block"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_BLOCK = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_block"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of a block in a case statement when the block is the first statement following
+ * the case
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_block_in_case"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of an enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of an enum declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_enum_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of a switch statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_SWITCH = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_switch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to position the braces of a type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration"
+ * - possible values: { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+ * - default: END_OF_LINE
+ *
+ * @see #END_OF_LINE
+ * @see #NEXT_LINE
+ * @see #NEXT_LINE_SHIFTED
+ * @see #NEXT_LINE_ON_WRAP
+ *
+ */
+ public static final String FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.brace_position_for_type_declaration"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether blank lines are cleared inside comments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ * @deprecated Use {@link #FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT} and {@link #FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT}
+ */
+ public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES = "org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether blank lines are cleared inside jsdoc comments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT = "org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether blank lines are cleared inside block comments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_BLOCK_COMMENT = "org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether comments are formatted
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_comments"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ * @deprecated Use multiple settings for each kind of comments. See {@link #FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT},
+ * {@link #FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT} and {@link #FORMATTER_COMMENT_FORMAT_LINE_COMMENT}.
+ */
+ public final static String FORMATTER_COMMENT_FORMAT = "org.eclipse.wst.jsdt.core.formatter.comment.format_comments"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether single line comments are formatted
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_FORMAT_LINE_COMMENT = "org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether multiple lines comments are formatted
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT = "org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether jsdoc comments are formatted
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT = "org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether the header comment of a JavaScript source file is formatted
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_header"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_FORMAT_HEADER = "org.eclipse.wst.jsdt.core.formatter.comment.format_header"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether HTML tags are formatted.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_html"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_FORMAT_HTML = "org.eclipse.wst.jsdt.core.formatter.comment.format_html"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether code snippets are formatted in comments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.format_source_code"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_FORMAT_SOURCE = "org.eclipse.wst.jsdt.core.formatter.comment.format_source_code"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether description of jsdoc parameters are indented
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_INDENT_PARAMETER_DESCRIPTION = "org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to control whether jsdoc root tags are indented.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public final static String FORMATTER_COMMENT_INDENT_ROOT_TAGS = "org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert an empty line before the jsdoc root tag block
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public final static String FORMATTER_COMMENT_INSERT_EMPTY_LINE_BEFORE_ROOT_TAGS = "org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a new line after jsdoc root tag parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public final static String FORMATTER_COMMENT_INSERT_NEW_LINE_FOR_PARAMETER = "org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to specify the line length for comments.
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.comment.line_length"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "80"
+ *
+ *
+ */
+ public final static String FORMATTER_COMMENT_LINE_LENGTH = "org.eclipse.wst.jsdt.core.formatter.comment.line_length"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to compact else/if
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.compact_else_if"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_COMPACT_ELSE_IF = JavaScriptCore.PLUGIN_ID + ".formatter.compact_else_if"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to set the continuation indentation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.continuation_indentation"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "2"
+ *
+ *
+ */
+ public static final String FORMATTER_CONTINUATION_INDENTATION = JavaScriptCore.PLUGIN_ID + ".formatter.continuation_indentation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to set the continuation indentation inside array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "2"
+ *
+ *
+ */
+ public static final String FORMATTER_CONTINUATION_INDENTATION_FOR_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.continuation_indentation_for_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to set the continuation indentation inside object literals initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "1"
+ *
+ *
+ */
+ public static final String FORMATTER_CONTINUATION_INDENTATION_FOR_OBJLIT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.continuation_indentation_for_objlit_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent body declarations compare to its enclosing annotation declaration header
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ANNOTATION_DECLARATION_HEADER = JavaScriptCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_annotation_declaration_header"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent body declarations compare to its enclosing enum constant header
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_CONSTANT_HEADER = JavaScriptCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_enum_constant_header"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent body declarations compare to its enclosing enum declaration header
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_ENUM_DECLARATION_HEADER = JavaScriptCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_enum_declaration_header"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent body declarations compare to its enclosing type header
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER = JavaScriptCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_type_header"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent breaks compare to cases
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_BREAKS_COMPARE_TO_CASES = JavaScriptCore.PLUGIN_ID + ".formatter.indent_breaks_compare_to_cases"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent empty lines
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_empty_lines"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_EMPTY_LINES = JavaScriptCore.PLUGIN_ID + ".formatter.indent_empty_lines"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent statements inside a block
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BLOCK = JavaScriptCore.PLUGIN_ID + ".formatter.indent_statements_compare_to_block"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent statements inside the body of a method or a constructor
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BODY = JavaScriptCore.PLUGIN_ID + ".formatter.indent_statements_compare_to_body"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent switch statements compare to cases
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES = JavaScriptCore.PLUGIN_ID + ".formatter.indent_switchstatements_compare_to_cases"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent switch statements compare to switch
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH = JavaScriptCore.PLUGIN_ID + ".formatter.indent_switchstatements_compare_to_switch"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to specify the equivalent number of spaces that represents one indentation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.indentation.size"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "4"
+ *
+ * This option is used only if the tab char is set to MIXED.
+ *
+ * @see #FORMATTER_TAB_CHAR
+ *
+ */
+ public static final String FORMATTER_INDENTATION_SIZE = JavaScriptCore.PLUGIN_ID + ".formatter.indentation.size"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a new line after an annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_after_annotation";//$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a new line after the opening brace in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_after_opening_brace_in_array_initializer";//$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a new line after the opening brace in an object literal initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_OBJLIT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_after_opening_brace_in_objlit_initializer";//$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a new line after each comma in an object literal initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_AFTER_COMMA_IN_OBJLIT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_after_comma_in_objlit_initializer";//$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a new line at the end of the current file if missing
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_AT_END_OF_FILE_IF_MISSING = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_at_end_of_file_if_missing";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line before the catch keyword in try statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_CATCH_IN_TRY_STATEMENT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_before_catch_in_try_statement"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line before the closing brace in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_before_closing_brace_in_array_initializer";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line before the closing brace in an object literal initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_OBJLIT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_before_closing_brace_in_objlit_initializer";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line before the else keyword in if statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_ELSE_IN_IF_STATEMENT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_before_else_in_if_statement"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line before the finally keyword in try statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_FINALLY_IN_TRY_STATEMENT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_before_finally_in_try_statement"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line before while in do statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_WHILE_IN_DO_STATEMENT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_before_while_in_do_statement"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty annotation declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANNOTATION_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_annotation_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty anonymous type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_anonymous_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty block
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_block"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty enum declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ENUM_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_enum_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty method body
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_method_body"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a new line in an empty type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after and in wilcard
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_AND_IN_TYPE_PARAMETER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_and_in_type_parameter"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after an assignment operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_assignment_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after at in annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_at_in_annotation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after at in annotation type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_AT_IN_ANNOTATION_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_at_in_annotation_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after a binary operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_binary_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the closing angle bracket in type arguments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_closing_angle_bracket_in_type_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the closing angle bracket in type parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_closing_angle_bracket_in_type_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the closing brace of a block
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_BRACE_IN_BLOCK = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_closing_brace_in_block"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the closing parenthesis of a cast expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_closing_paren_in_cast"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the colon in an assert statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_ASSERT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_assert"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after colon in a case statement when a opening brace follows the colon
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CASE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_case"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the colon in an object initializer expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_object_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_OBJECT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_object_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the colon in a conditional expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_conditional"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after colon in a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the colon in a labeled statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_labeled_statement"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in an allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_allocation_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_annotation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the parameters of a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_DECLARATION_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_constructor_declaration_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the exception names in a throws clause of a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_DECLARATION_THROWS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_constructor_declaration_throws"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the arguments of an enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_CONSTANT_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_enum_constant_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in enum declarations
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ENUM_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_enum_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the arguments of an explicit constructor call
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_EXPLICIT_CONSTRUCTOR_CALL_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the increments of a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_for_increments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the initializations of a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_for_inits"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the parameters of a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_DECLARATION_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_method_declaration_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the exception names in a throws clause of a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_DECLARATION_THROWS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_method_declaration_throws"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in the arguments of a method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_INVOCATION_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_method_invocation_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in multiple field declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_multiple_field_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in multiple local declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_multiple_local_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in parameterized type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_parameterized_type_reference"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in superinterfaces names of a type header
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_superinterfaces"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in type arguments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_type_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the comma in type parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_TYPE_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_type_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after ellipsis
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_ELLIPSIS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_ellipsis"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening angle bracket in parameterized type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening angle bracket in type arguments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_angle_bracket_in_type_arguments";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening angle bracket in type parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_angle_bracket_in_type_parameters";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening brace in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_brace_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening bracket inside an array allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_bracket_in_array_allocation_expression";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening bracket inside an array reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACKET_IN_ARRAY_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_bracket_in_array_reference";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_annotation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a cast expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_cast"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a catch
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CATCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_catch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in an if statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_IF = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_if"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_METHOD_INVOCATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_method_invocation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a parenthesized expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_PARENTHESIZED_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_parenthesized_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a switch statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_SWITCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_switch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a synchronized statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_SYNCHRONIZED = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_synchronized"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after the opening parenthesis in a while statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_WHILE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_while"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after a postfix operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_postfix_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after a prefix operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_PREFIX_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_prefix_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after question mark in a conditional expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_question_in_conditional"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after semicolon in a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_semicolon_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space after an unary operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_AFTER_UNARY_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_after_unary_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before an assignment operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_assignment_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before at in annotation type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_AT_IN_ANNOTATION_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_at_in_annotation_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before an binary operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_binary_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing angle bracket in parameterized type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing angle bracket in type arguments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_angle_bracket_in_type_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing angle bracket in type parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_angle_bracket_in_type_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing brace in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_brace_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing bracket in an array allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_bracket_in_array_allocation_expression";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing bracket in an array reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACKET_IN_ARRAY_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_bracket_in_array_reference";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_annotation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a cast expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_cast"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a catch
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CATCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_catch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in an if statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_IF = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_if"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_METHOD_INVOCATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_method_invocation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a parenthesized expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_PARENTHESIZED_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_parenthesized_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a switch statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_SWITCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_switch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a synchronized statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_SYNCHRONIZED = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_synchronized"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the closing parenthesis in a while statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_WHILE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_while"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in an assert statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_ASSERT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_assert"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in a case statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CASE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_case"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in an object initializer expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_object_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_OBJECT_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_object_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in a conditional expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_conditional"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in a default statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_default"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before colon in a labeled statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_labeled_statement"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in an allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_allocation_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_annotation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the parameters of a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_DECLARATION_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_constructor_declaration_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the exception names of the throws clause of a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_DECLARATION_THROWS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_constructor_declaration_throws"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the arguments of enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_CONSTANT_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_enum_constant_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in enum declarations
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ENUM_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_enum_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the arguments of an explicit constructor call
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICIT_CONSTRUCTOR_CALL_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the increments of a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_for_increments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the initializations of a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_for_inits"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the parameters of a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_DECLARATION_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_method_declaration_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the exception names of the throws clause of a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_DECLARATION_THROWS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_method_declaration_throws"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the arguments of a method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_INVOCATION_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_method_invocation_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in a multiple field declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_multiple_field_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in a multiple local declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_multiple_local_declarations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in parameterized type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_PARAMETERIZED_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_parameterized_type_reference"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in the superinterfaces names in a type header
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_superinterfaces"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in type arguments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_type_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before comma in type parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_TYPE_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_type_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before ellipsis
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_ELLIPSIS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_ellipsis"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening angle bracket in parameterized type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_PARAMETERIZED_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening angle bracket in type arguments
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_angle_bracket_in_type_arguments"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening angle bracket in type parameters
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETERS = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_angle_bracket_in_type_parameters"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in an annotation type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANNOTATION_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_annotation_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in an anonymous type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ANONYMOUS_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ * @deprecated No longer used internally. Will be removed in future release.
+ * Preference is overshadowed by {@link #FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR}
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in a block
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_BLOCK = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_block"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in an enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in an enum declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ENUM_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_enum_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in a switch statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_SWITCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_switch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening brace in a type declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_TYPE_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_type_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening bracket in an array allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_bracket_in_array_allocation_expression";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening bracket in an array reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_bracket_in_array_reference";//$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening bracket in an array type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACKET_IN_ARRAY_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_bracket_in_array_type_reference"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in annotation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_annotation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in annotation type member declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ANNOTATION_TYPE_MEMBER_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a catch
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_CATCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_catch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in an if statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_IF = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_if"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_METHOD_INVOCATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_method_invocation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a parenthesized expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_PARENTHESIZED_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_parenthesized_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a switch statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_SWITCH = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_switch"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a synchronized statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_SYNCHRONIZED = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_synchronized"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before the opening parenthesis in a while statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_PAREN_IN_WHILE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_opening_paren_in_while"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before parenthesized expression in return statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_PARENTHESIZED_EXPRESSION_IN_RETURN = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_parenthesized_expression_in_return"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before parenthesized expression in throw statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_PARENTHESIZED_EXPRESSION_IN_THROW = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_parenthesized_expression_in_throw"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before a postfix operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_postfix_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before a prefix operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_PREFIX_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_prefix_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before question mark in a conditional expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_question_in_conditional"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before semicolon
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_semicolon"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before semicolon in for statement
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON_IN_FOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_semicolon_in_for"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space before unary operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BEFORE_UNARY_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_before_unary_operator"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to insert a space between brackets in an array type reference
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_brackets_in_array_type_reference"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty braces in an array initializer
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_BRACES_IN_ARRAY_INITIALIZER = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_braces_in_array_initializer"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty brackets in an array allocation expression
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_BRACKETS_IN_ARRAY_ALLOCATION_EXPRESSION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_brackets_in_array_allocation_expression"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty parenthesis in an annotation type member declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ANNOTATION_TYPE_MEMBER_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty parenthesis in a constructor declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_CONSTRUCTOR_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_constructor_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty parenthesis in enum constant
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_ENUM_CONSTANT = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_enum_constant"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty parenthesis in a method declaration
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_METHOD_DECLARATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_method_declaration"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to insert a space between empty parenthesis in a method invocation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation"
+ * - possible values: { INSERT, DO_NOT_INSERT }
+ * - default: DO_NOT_INSERT
+ *
+ * @see JavaScriptCore#INSERT
+ * @see JavaScriptCore#DO_NOT_INSERT
+ *
+ */
+ public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_PARENS_IN_METHOD_INVOCATION = JavaScriptCore.PLUGIN_ID + ".formatter.insert_space_between_empty_parens_in_method_invocation"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to keep else statement on the same line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_KEEP_ELSE_STATEMENT_ON_SAME_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.keep_else_statement_on_same_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to keep empty array initializer one one line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_KEEP_EMPTY_ARRAY_INITIALIZER_ON_ONE_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.keep_empty_array_initializer_on_one_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to keep empty object literal initializer one one line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_KEEP_EMPTY_OBJLIT_INITIALIZER_ON_ONE_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.keep_empty_objlit_initializer_on_one_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to keep guardian clause on one line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_KEEP_GUARDIAN_CLAUSE_ON_ONE_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.format_guardian_clause_on_one_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to keep simple if statement on the one line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_KEEP_SIMPLE_IF_ON_ONE_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.keep_imple_if_on_one_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to keep then statement on the same line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_KEEP_THEN_STATEMENT_ON_SAME_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.keep_then_statement_on_same_line";//$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to specify the length of the page. Beyond this length, the formatter will try to split the code
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.lineSplit"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "80"
+ *
+ *
+ */
+ public static final String FORMATTER_LINE_SPLIT = JavaScriptCore.PLUGIN_ID + ".formatter.lineSplit"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent block comments that start on the first column
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.formatter.never_indent_block_comments_on_first_column"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * Note that this option is ignored if the formatter is created with the mode {@link org.eclipse.wst.jsdt.core.ToolFactory#M_FORMAT_NEW}.
+ * @see #TRUE
+ * @see #FALSE
+ * @see org.eclipse.wst.jsdt.core.ToolFactory#createCodeFormatter(Map, int)
+ *
+ */
+ public static final String FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN = JavaScriptCore.PLUGIN_ID + ".formatter.never_indent_block_comments_on_first_column"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to indent line comments that start on the first column
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.formatter.never_indent_line_comments_on_first_column"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * Note that this option is ignored if the formatter is created with the mode {@link org.eclipse.wst.jsdt.core.ToolFactory#M_FORMAT_NEW}.
+ * @see #TRUE
+ * @see #FALSE
+ * @see org.eclipse.wst.jsdt.core.ToolFactory#createCodeFormatter(Map, int)
+ *
+ */
+ public static final String FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN = JavaScriptCore.PLUGIN_ID + ".formatter.never_indent_line_comments_on_first_column"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to specify the number of empty lines to preserve
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "0"
+ *
+ *
+ */
+ public static final String FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE = JavaScriptCore.PLUGIN_ID + ".formatter.number_of_empty_lines_to_preserve"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to specify whether or not empty statement should be on a new line
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE = JavaScriptCore.PLUGIN_ID + ".formatter.put_empty_statement_on_new_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to specify the tabulation size
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.tabulation.char"
+ * - possible values: { TAB, SPACE, MIXED }
+ * - default: TAB
+ *
+ * More values may be added in the future.
+ *
+ * @see JavaScriptCore#TAB
+ * @see JavaScriptCore#SPACE
+ * @see #MIXED
+ *
+ */
+ public static final String FORMATTER_TAB_CHAR = JavaScriptCore.PLUGIN_ID + ".formatter.tabulation.char"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to specify the equivalent number of spaces that represents one tabulation
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.tabulation.size"
+ * - possible values: "<n>", where n is zero or a positive integer
+ * - default: "4"
+ *
+ *
+ */
+ public static final String FORMATTER_TAB_SIZE = JavaScriptCore.PLUGIN_ID + ".formatter.tabulation.size"; //$NON-NLS-1$
+
+ /**
+ *
+ * FORMATTER / Option to use tabulations only for leading indentations
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations"
+ * - possible values: { TRUE, FALSE }
+ * - default: FALSE
+ *
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_USE_TABS_ONLY_FOR_LEADING_INDENTATIONS = JavaScriptCore.PLUGIN_ID + ".formatter.use_tabs_only_for_leading_indentations"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Option to wrap before the binary operator
+ * - option id: "org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator"
+ * - possible values: { TRUE, FALSE }
+ * - default: TRUE
+ *
+ * This option is used only if the option {@link #FORMATTER_ALIGNMENT_FOR_BINARY_EXPRESSION} is set.
+ * @see #TRUE
+ * @see #FALSE
+ *
+ */
+ public static final String FORMATTER_WRAP_BEFORE_BINARY_OPERATOR = JavaScriptCore.PLUGIN_ID + ".formatter.wrap_before_binary_operator"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / The wrapping is done by indenting by one compare to the current indentation.
+ *
+ *
+ */
+ public static final int INDENT_BY_ONE= 2;
+
+ /**
+ *
+ * FORMATTER / The wrapping is done by using the current indentation.
+ *
+ *
+ */
+ public static final int INDENT_DEFAULT= 0;
+ /**
+ *
+ * FORMATTER / The wrapping is done by indenting on column under the splitting location.
+ *
+ *
+ */
+ public static final int INDENT_ON_COLUMN = 1;
+
+ /**
+ *
+ * FORMATTER / Possible value for the option FORMATTER_TAB_CHAR
+ *
+ *
+ * @see JavaScriptCore#TAB
+ * @see JavaScriptCore#SPACE
+ * @see #FORMATTER_TAB_CHAR
+ */
+ public static final String MIXED = "mixed"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Value to set a brace location at the start of the next line with
+ * the right indentation.
+ *
+ * @see #FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_OBJLIT_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_BLOCK
+ * @see #FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_SWITCH
+ * @see #FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION
+ *
+ */
+ public static final String NEXT_LINE = "next_line"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Value to set a brace location at the start of the next line if a wrapping
+ * occured.
+ *
+ * @see #FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_OBJLIT_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_BLOCK
+ * @see #FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_SWITCH
+ * @see #FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION
+ *
+ */
+ public static final String NEXT_LINE_ON_WRAP = "next_line_on_wrap"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Value to set a brace location at the start of the next line with
+ * an extra indentation.
+ *
+ * @see #FORMATTER_BRACE_POSITION_FOR_ANONYMOUS_TYPE_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_OBJLIT_INITIALIZER
+ * @see #FORMATTER_BRACE_POSITION_FOR_BLOCK
+ * @see #FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION
+ * @see #FORMATTER_BRACE_POSITION_FOR_SWITCH
+ * @see #FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION
+ *
+ */
+ public static final String NEXT_LINE_SHIFTED = "next_line_shifted"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / Value to set an option to true.
+ *
+ *
+ */
+ public static final String TRUE = "true"; //$NON-NLS-1$
+ /**
+ *
+ * FORMATTER / The wrapping is done using as few lines as possible.
+ *
+ *
+ */
+ public static final int WRAP_COMPACT= 1;
+ /**
+ *
+ * FORMATTER / The wrapping is done putting the first element on a new
+ * line and then wrapping next elements using as few lines as possible.
+ *
+ *
+ */
+ public static final int WRAP_COMPACT_FIRST_BREAK= 2;
+ /**
+ *
+ * FORMATTER / The wrapping is done by putting each element on its own line
+ * except the first element.
+ *
+ *
+ */
+ public static final int WRAP_NEXT_PER_LINE= 5;
+ /**
+ *
+ * FORMATTER / The wrapping is done by putting each element on its own line.
+ * All elements are indented by one except the first element.
+ *
+ *
+ */
+ public static final int WRAP_NEXT_SHIFTED= 4;
+
+ /**
+ *
+ * FORMATTER / Value to disable alignment.
+ *
+ *
+ */
+ public static final int WRAP_NO_SPLIT= 0;
+ /**
+ *
+ * FORMATTER / The wrapping is done by putting each element on its own line.
+ *
+ *
+ */
+ public static final int WRAP_ONE_PER_LINE= 3;
+
+ /*
+ * Private constants. Not in javadoc
+ */
+ private static final IllegalArgumentException WRONG_ARGUMENT = new IllegalArgumentException();
+ /**
+ * Create a new alignment value according to the given values. This must be used to set up
+ * the alignment options.
+ *
+ * @param forceSplit the given force value
+ * @param wrapStyle the given wrapping style
+ * @param indentStyle the given indent style
+ *
+ * @return the new alignement value
+ */
+ public static String createAlignmentValue(boolean forceSplit, int wrapStyle, int indentStyle) {
+ int alignmentValue = 0;
+ switch(wrapStyle) {
+ case WRAP_COMPACT :
+ alignmentValue |= Alignment.M_COMPACT_SPLIT;
+ break;
+ case WRAP_COMPACT_FIRST_BREAK :
+ alignmentValue |= Alignment.M_COMPACT_FIRST_BREAK_SPLIT;
+ break;
+ case WRAP_NEXT_PER_LINE :
+ alignmentValue |= Alignment.M_NEXT_PER_LINE_SPLIT;
+ break;
+ case WRAP_NEXT_SHIFTED :
+ alignmentValue |= Alignment.M_NEXT_SHIFTED_SPLIT;
+ break;
+ case WRAP_ONE_PER_LINE :
+ alignmentValue |= Alignment.M_ONE_PER_LINE_SPLIT;
+ break;
+ }
+ if (forceSplit) {
+ alignmentValue |= Alignment.M_FORCE;
+ }
+ switch(indentStyle) {
+ case INDENT_BY_ONE :
+ alignmentValue |= Alignment.M_INDENT_BY_ONE;
+ break;
+ case INDENT_ON_COLUMN :
+ alignmentValue |= Alignment.M_INDENT_ON_COLUMN;
+ }
+ return String.valueOf(alignmentValue);
+ }
+
+ /**
+ * Returns the formatter settings that most closely approximate
+ * the default formatter settings of Eclipse version 2.1.
+ *
+ * @return the Eclipse 2.1 settings
+ *
+ */
+ public static Map getEclipse21Settings() {
+ return DefaultCodeFormatterOptions.getDefaultSettings().getMap();
+ }
+
+ /**
+ * Returns the default Eclipse formatter settings
+ *
+ * @return the Eclipse default settings
+ *
+ */
+ public static Map getEclipseDefaultSettings() {
+ return DefaultCodeFormatterOptions.getEclipseDefaultSettings().getMap();
+ }
+
+ /**
+ * Return the force value of the given alignment value.
+ * The given alignment value should be created using the createAlignmentValue(boolean, int, int)
+ * API.
+ *
+ *
+ * @param value the given alignment value
+ * @return the force value of the given alignment value
+ * @see #createAlignmentValue(boolean, int, int)
+ * @exception IllegalArgumentException if the given alignment value is null, or if it
+ * doesn't have a valid format.
+ */
+ public static boolean getForceWrapping(String value) {
+ if (value == null) {
+ throw WRONG_ARGUMENT;
+ }
+ try {
+ int existingValue = Integer.parseInt(value);
+ return (existingValue & Alignment.M_FORCE) != 0;
+ } catch (NumberFormatException e) {
+ throw WRONG_ARGUMENT;
+ }
+ }
+
+ /**
+ * Return the indentation style of the given alignment value.
+ * The given alignment value should be created using the createAlignmentValue(boolean, int, int)
+ * API.
+ *
+ *
+ * @param value the given alignment value
+ * @return the indentation style of the given alignment value
+ * @see #createAlignmentValue(boolean, int, int)
+ * @exception IllegalArgumentException if the given alignment value is null, or if it
+ * doesn't have a valid format.
+ */
+ public static int getIndentStyle(String value) {
+ if (value == null) {
+ throw WRONG_ARGUMENT;
+ }
+ try {
+ int existingValue = Integer.parseInt(value);
+ if ((existingValue & Alignment.M_INDENT_BY_ONE) != 0) {
+ return INDENT_BY_ONE;
+ } else if ((existingValue & Alignment.M_INDENT_ON_COLUMN) != 0) {
+ return INDENT_ON_COLUMN;
+ } else {
+ return INDENT_DEFAULT;
+ }
+ } catch (NumberFormatException e) {
+ throw WRONG_ARGUMENT;
+ }
+ }
+
+ /**
+ * Returns the settings according to the JavaScript conventions.
+ *
+ * @return the settings according to the JavaScript conventions
+ *
+ */
+ public static Map getJavaConventionsSettings() {
+ return DefaultCodeFormatterOptions.getJavaConventionsSettings().getMap();
+ }
+ /**
+ * Return the wrapping style of the given alignment value.
+ * The given alignment value should be created using the createAlignmentValue(boolean, int, int)
+ * API.
+ *
+ *
+ * @param value the given alignment value
+ * @return the wrapping style of the given alignment value
+ * @see #createAlignmentValue(boolean, int, int)
+ * @exception IllegalArgumentException if the given alignment value is null, or if it
+ * doesn't have a valid format.
+ */
+ public static int getWrappingStyle(String value) {
+ if (value == null) {
+ throw WRONG_ARGUMENT;
+ }
+ try {
+ int existingValue = Integer.parseInt(value) & Alignment.SPLIT_MASK;
+ switch(existingValue) {
+ case Alignment.M_COMPACT_SPLIT :
+ return WRAP_COMPACT;
+ case Alignment.M_COMPACT_FIRST_BREAK_SPLIT :
+ return WRAP_COMPACT_FIRST_BREAK;
+ case Alignment.M_NEXT_PER_LINE_SPLIT :
+ return WRAP_NEXT_PER_LINE;
+ case Alignment.M_NEXT_SHIFTED_SPLIT :
+ return WRAP_NEXT_SHIFTED;
+ case Alignment.M_ONE_PER_LINE_SPLIT :
+ return WRAP_ONE_PER_LINE;
+ default:
+ return WRAP_NO_SPLIT;
+ }
+ } catch (NumberFormatException e) {
+ throw WRONG_ARGUMENT;
+ }
+ }
+ /**
+ * Set the force value of the given alignment value and return the new value.
+ * The given alignment value should be created using the createAlignmentValue(boolean, int, int)
+ * API.
+ *
+ *
+ * @param value the given alignment value
+ * @param force the given force value
+ * @return the new alignment value
+ * @see #createAlignmentValue(boolean, int, int)
+ * @exception IllegalArgumentException if the given alignment value is null, or if it
+ * doesn't have a valid format.
+ */
+ public static String setForceWrapping(String value, boolean force) {
+ if (value == null) {
+ throw WRONG_ARGUMENT;
+ }
+ try {
+ int existingValue = Integer.parseInt(value);
+ // clear existing force bit
+ existingValue &= ~Alignment.M_FORCE;
+ if (force) {
+ existingValue |= Alignment.M_FORCE;
+ }
+ return String.valueOf(existingValue);
+ } catch (NumberFormatException e) {
+ throw WRONG_ARGUMENT;
+ }
+ }
+
+ /**
+ * Set the indentation style of the given alignment value and return the new value.
+ * The given value should be created using the createAlignmentValue(boolean, int, int)
+ * API.
+ *
+ *
+ * @param value the given alignment value
+ * @param indentStyle the given indentation style
+ * @return the new alignment value
+ * @see #INDENT_BY_ONE
+ * @see #INDENT_DEFAULT
+ * @see #INDENT_ON_COLUMN
+ * @see #createAlignmentValue(boolean, int, int)
+ * @exception IllegalArgumentException if the given alignment value is null, if the given
+ * indentation style is not one of the possible indentation styles, or if the given
+ * alignment value doesn't have a valid format.
+ */
+ public static String setIndentStyle(String value, int indentStyle) {
+ if (value == null) {
+ throw WRONG_ARGUMENT;
+ }
+ switch(indentStyle) {
+ case INDENT_BY_ONE :
+ case INDENT_DEFAULT :
+ case INDENT_ON_COLUMN :
+ break;
+ default :
+ throw WRONG_ARGUMENT;
+ }
+ try {
+ int existingValue = Integer.parseInt(value);
+ // clear existing indent bits
+ existingValue &= ~(Alignment.M_INDENT_BY_ONE | Alignment.M_INDENT_ON_COLUMN);
+ switch(indentStyle) {
+ case INDENT_BY_ONE :
+ existingValue |= Alignment.M_INDENT_BY_ONE;
+ break;
+ case INDENT_ON_COLUMN :
+ existingValue |= Alignment.M_INDENT_ON_COLUMN;
+ }
+ return String.valueOf(existingValue);
+ } catch (NumberFormatException e) {
+ throw WRONG_ARGUMENT;
+ }
+ }
+ /**
+ * Set the wrapping style of the given alignment value and return the new value.
+ * The given value should be created using the createAlignmentValue(boolean, int, int)
+ * API.
+ *
+ *
+ * @param value the given alignment value
+ * @param wrappingStyle the given wrapping style
+ * @return the new alignment value
+ * @see #WRAP_COMPACT
+ * @see #WRAP_COMPACT_FIRST_BREAK
+ * @see #WRAP_NEXT_PER_LINE
+ * @see #WRAP_NEXT_SHIFTED
+ * @see #WRAP_NO_SPLIT
+ * @see #WRAP_ONE_PER_LINE
+ * @see #createAlignmentValue(boolean, int, int)
+ * @exception IllegalArgumentException if the given alignment value is null, if the given
+ * wrapping style is not one of the possible wrapping styles, or if the given
+ * alignment value doesn't have a valid format.
+ */
+ public static String setWrappingStyle(String value, int wrappingStyle) {
+ if (value == null) {
+ throw WRONG_ARGUMENT;
+ }
+ switch(wrappingStyle) {
+ case WRAP_COMPACT :
+ case WRAP_COMPACT_FIRST_BREAK :
+ case WRAP_NEXT_PER_LINE :
+ case WRAP_NEXT_SHIFTED :
+ case WRAP_NO_SPLIT :
+ case WRAP_ONE_PER_LINE :
+ break;
+ default:
+ throw WRONG_ARGUMENT;
+ }
+ try {
+ int existingValue = Integer.parseInt(value);
+ // clear existing split bits
+ existingValue &= ~(Alignment.SPLIT_MASK);
+ switch(wrappingStyle) {
+ case WRAP_COMPACT :
+ existingValue |= Alignment.M_COMPACT_SPLIT;
+ break;
+ case WRAP_COMPACT_FIRST_BREAK :
+ existingValue |= Alignment.M_COMPACT_FIRST_BREAK_SPLIT;
+ break;
+ case WRAP_NEXT_PER_LINE :
+ existingValue |= Alignment.M_NEXT_PER_LINE_SPLIT;
+ break;
+ case WRAP_NEXT_SHIFTED :
+ existingValue |= Alignment.M_NEXT_SHIFTED_SPLIT;
+ break;
+ case WRAP_ONE_PER_LINE :
+ existingValue |= Alignment.M_ONE_PER_LINE_SPLIT;
+ break;
+ }
+ return String.valueOf(existingValue);
+ } catch (NumberFormatException e) {
+ throw WRONG_ARGUMENT;
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/IndentManipulation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/IndentManipulation.java
new file mode 100644
index 0000000..282d6d6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/IndentManipulation.java
@@ -0,0 +1,429 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.formatter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+/**
+ * Helper class to provide String manipulation functions dealing with indentations.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class IndentManipulation {
+
+ private IndentManipulation() {
+ // don't instantiate
+ }
+
+ /**
+ * Returns true
if the given character is an indentation character. Indentation character are all whitespace characters
+ * except the line delimiter characters.
+ *
+ * @param ch the given character
+ * @return Returns true
if this the character is a indent character, false
otherwise
+ */
+ public static boolean isIndentChar(char ch) {
+ return ScannerHelper.isWhitespace(ch) && !isLineDelimiterChar(ch);
+ }
+
+ /**
+ * Returns true
if the given character is a line delimiter character.
+ *
+ * @param ch the given character
+ * @return Returns true
if this the character is a line delimiter character, false
otherwise
+ */
+ public static boolean isLineDelimiterChar(char ch) {
+ return ch == '\n' || ch == '\r';
+ }
+
+ /**
+ * Returns the indentation of the given line in indentation units. Odd spaces are
+ * not counted. This method only analyzes the content of line
up to the first
+ * non-whitespace character.
+ *
+ * @param line the string to measure the indent of
+ * @param tabWidth the width of one tab character in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @return the number of indentation units that line is indented by
+ * @exception IllegalArgumentException if:
+ *
+ * - the given
indentWidth
is lower or equals to zero
+ * - the given
tabWidth
is lower than zero
+ * - the given
line
is null
+ *
+ */
+ public static int measureIndentUnits(CharSequence line, int tabWidth, int indentWidth) {
+ if (indentWidth <= 0 || tabWidth < 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ int visualLength= measureIndentInSpaces(line, tabWidth);
+ return visualLength / indentWidth;
+ }
+
+ /**
+ * Returns the indentation of the given line in space equivalents.
+ *
+ * Tab characters are counted using the given tabWidth
and every other indent
+ * character as one. This method analyzes the content of line
up to the first
+ * non-whitespace character.
+ *
+ * @param line the string to measure the indent of
+ * @param tabWidth the width of one tab in space equivalents
+ * @return the measured indent width in space equivalents
+ * @exception IllegalArgumentException if:
+ *
+ * - the given
line
is null
+ * - the given
tabWidth
is lower than zero
+ *
+ */
+ public static int measureIndentInSpaces(CharSequence line, int tabWidth) {
+ if (tabWidth < 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ int length= 0;
+ int max= line.length();
+ for (int i= 0; i < max; i++) {
+ char ch= line.charAt(i);
+ if (ch == '\t') {
+ int reminder= length % tabWidth;
+ length += tabWidth - reminder;
+ } else if (isIndentChar(ch)) {
+ length++;
+ } else {
+ return length;
+ }
+ }
+ return length;
+ }
+
+ /**
+ * Returns the leading indentation string of the given line. Note that the returned string
+ * need not be equal to the leading whitespace as odd spaces are not considered part of the
+ * indentation.
+ *
+ * @param line the line to scan
+ * @param tabWidth the size of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @return the indent part of line
, but no odd spaces
+ * @exception IllegalArgumentException if:
+ *
+ * - the given
indentWidth
is lower or equals to zero
+ * - the given
tabWidth
is lower than zero
+ * - the given
line
is null
+ *
+ */
+ public static String extractIndentString(String line, int tabWidth, int indentWidth) {
+ if (tabWidth < 0 || indentWidth <= 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ int size= line.length();
+ int end= 0;
+
+ int spaceEquivs= 0;
+ int characters= 0;
+ for (int i= 0; i < size; i++) {
+ char c= line.charAt(i);
+ if (c == '\t') {
+ int remainder= spaceEquivs % tabWidth;
+ spaceEquivs += tabWidth - remainder;
+ characters++;
+ } else if (isIndentChar(c)) {
+ spaceEquivs++;
+ characters++;
+ } else {
+ break;
+ }
+ if (spaceEquivs >= indentWidth) {
+ end += characters;
+ characters= 0;
+ spaceEquivs= spaceEquivs % indentWidth;
+ }
+ }
+ if (end == 0) {
+ return Util.EMPTY_STRING;
+ } else if (end == size) {
+ return line;
+ } else {
+ return line.substring(0, end);
+ }
+ }
+
+
+ /**
+ * Removes the given number of indentation units from a given line. If the line
+ * has less than the given indent, all the available indentation is removed.
+ * If indentsToRemove <= 0
the line is returned.
+ *
+ * @param line the line to trim
+ * @param tabWidth the width of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @return the trimmed string
+ * @exception IllegalArgumentException if:
+ *
+ * - the given
indentWidth
is lower or equals to zero
+ * - the given
tabWidth
is lower than zero
+ * - the given
line
is null
+ *
+ */
+ public static String trimIndent(String line, int indentUnitsToRemove, int tabWidth, int indentWidth) {
+ if (tabWidth < 0 || indentWidth <= 0 || line == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (indentUnitsToRemove <= 0)
+ return line;
+
+ final int spaceEquivalentsToRemove= indentUnitsToRemove * indentWidth;
+
+ int start= 0;
+ int spaceEquivalents= 0;
+ int size= line.length();
+ String prefix= null;
+ for (int i= 0; i < size; i++) {
+ char c= line.charAt(i);
+ if (c == '\t') {
+ int remainder= spaceEquivalents % tabWidth;
+ spaceEquivalents += tabWidth - remainder;
+ } else if (isIndentChar(c)) {
+ spaceEquivalents++;
+ } else {
+ // Assert.isTrue(false, "Line does not have requested number of indents");
+ start= i;
+ break;
+ }
+ if (spaceEquivalents == spaceEquivalentsToRemove) {
+ start= i + 1;
+ break;
+ }
+ if (spaceEquivalents > spaceEquivalentsToRemove) {
+ // can happen if tabSize > indentSize, e.g tabsize==8, indent==4, indentsToRemove==1, line prefixed with one tab
+ // this implements the third option
+ start= i + 1; // remove the tab
+ // and add the missing spaces
+ char[] missing= new char[spaceEquivalents - spaceEquivalentsToRemove];
+ Arrays.fill(missing, ' ');
+ prefix= new String(missing);
+ break;
+ }
+ }
+ String trimmed;
+ if (start == size)
+ trimmed= Util.EMPTY_STRING;
+ else
+ trimmed= line.substring(start);
+
+ if (prefix == null)
+ return trimmed;
+ return prefix + trimmed;
+ }
+
+ /**
+ * Change the indent of a, possible multiple line, code string. The given number of indent units is removed,
+ * and a new indent string is added.
+ * The first line of the code will not be changed (It is considered to have no indent as it might start in
+ * the middle of a line).
+ *
+ * @param code the code to change the indent of
+ * @param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code
+ * @param tabWidth the size of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @param newIndentString the new indent string to be added to all lines (except the first)
+ * @param lineDelim the new line delimiter to be used. The returned code will contain only this line delimiter.
+ * @return the newly indent code, containing only the given line delimiters.
+ * @exception IllegalArgumentException if:
+ *
+ * - the given
indentWidth
is lower or equals to zero
+ * - the given
tabWidth
is lower than zero
+ * - the given
code
is null
+ * - the given
indentUnitsToRemove
is lower than zero
+ * - the given
newIndentString
is null
+ * - the given
lineDelim
is null
+ *
+ */
+ public static String changeIndent(String code, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString, String lineDelim) {
+ if (tabWidth < 0 || indentWidth <= 0 || code == null || indentUnitsToRemove < 0 || newIndentString == null || lineDelim == null) {
+ throw new IllegalArgumentException();
+ }
+
+ try {
+ ILineTracker tracker= new DefaultLineTracker();
+ tracker.set(code);
+ int nLines= tracker.getNumberOfLines();
+ if (nLines == 1) {
+ return code;
+ }
+
+ StringBuffer buf= new StringBuffer();
+
+ for (int i= 0; i < nLines; i++) {
+ IRegion region= tracker.getLineInformation(i);
+ int start= region.getOffset();
+ int end= start + region.getLength();
+ String line= code.substring(start, end);
+
+ if (i == 0) { // no indent for first line (contained in the formatted string)
+ buf.append(line);
+ } else { // no new line after last line
+ buf.append(lineDelim);
+ buf.append(newIndentString);
+ buf.append(trimIndent(line, indentUnitsToRemove, tabWidth, indentWidth));
+ }
+ }
+ return buf.toString();
+ } catch (BadLocationException e) {
+ // can not happen
+ return code;
+ }
+ }
+
+ /**
+ * Returns the text edits retrieved after changing the indentation of a, possible multi-line, code string.
+ *
+ * The given number of indent units is removed, and a new indent string is added.
+ * The first line of the code will not be changed (It is considered to have no indent as it might start in
+ * the middle of a line).
+ *
+ * @param source The code to change the indent of
+ * @param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code
+ * @param tabWidth the size of one tab in space equivalents
+ * @param indentWidth the width of one indentation unit in space equivalents
+ * @param newIndentString the new indent string to be added to all lines (except the first)
+ * @return returns the resulting text edits
+ * @exception IllegalArgumentException if:
+ *
+ * - the given
indentWidth
is lower or equals to zero
+ * - the given
tabWidth
is lower than zero
+ * - the given
source
is null
+ * - the given
indentUnitsToRemove
is lower than zero
+ * - the given
newIndentString
is null
+ *
+ */
+ public static ReplaceEdit[] getChangeIndentEdits(String source, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString) {
+ if (tabWidth < 0 || indentWidth <= 0 || source == null || indentUnitsToRemove < 0 || newIndentString == null) {
+ throw new IllegalArgumentException();
+ }
+
+ ArrayList result= new ArrayList();
+ try {
+ ILineTracker tracker= new DefaultLineTracker();
+ tracker.set(source);
+ int nLines= tracker.getNumberOfLines();
+ if (nLines == 1)
+ return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
+ for (int i= 1; i < nLines; i++) {
+ IRegion region= tracker.getLineInformation(i);
+ int offset= region.getOffset();
+ String line= source.substring(offset, offset + region.getLength());
+ int length= indexOfIndent(line, indentUnitsToRemove, tabWidth, indentWidth);
+ if (length >= 0) {
+ result.add(new ReplaceEdit(offset, length, newIndentString));
+ } else {
+ length= measureIndentUnits(line, tabWidth, indentWidth);
+ result.add(new ReplaceEdit(offset, length, "")); //$NON-NLS-1$
+ }
+ }
+ } catch (BadLocationException cannotHappen) {
+ // can not happen
+ }
+ return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
+ }
+
+ /*
+ * Returns the index where the indent of the given size ends.
+ * Returns -1 if the line isn't prefixed with an indent of
+ * the given number of indents.
+ */
+ private static int indexOfIndent(CharSequence line, int numberOfIndentUnits, int tabWidth, int indentWidth) {
+
+ int spaceEquivalents= numberOfIndentUnits * indentWidth;
+
+ int size= line.length();
+ int result= -1;
+ int blanks= 0;
+ for (int i= 0; i < size && blanks < spaceEquivalents; i++) {
+ char c= line.charAt(i);
+ if (c == '\t') {
+ int remainder= blanks % tabWidth;
+ blanks += tabWidth - remainder;
+ } else if (isIndentChar(c)) {
+ blanks++;
+ } else {
+ break;
+ }
+ result= i;
+ }
+ if (blanks < spaceEquivalents)
+ return -1;
+ return result + 1;
+ }
+
+ /**
+ * Returns the tab width as configured in the given map.
+ * Use {@link org.eclipse.wst.jsdt.core.IJavaScriptProject#getOptions(boolean)} to get the most current project options.
+ *
+ * @param options the map to get the formatter settings from.
+ *
+ * @return the tab width
+ * @exception IllegalArgumentException if the given options
is null
+ */
+ public static int getTabWidth(Map options) {
+ if (options == null) {
+ throw new IllegalArgumentException();
+ }
+ return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 4);
+ }
+
+ /**
+ * Returns the tab width as configured in the given map.
+ * Use {@link org.eclipse.wst.jsdt.core.IJavaScriptProject#getOptions(boolean)} to get the most current project options.
+ *
+ * @param options the map to get the formatter settings from
+ *
+ * @return the indent width
+ * @exception IllegalArgumentException if the given options
is null
+ */
+ public static int getIndentWidth(Map options) {
+ if (options == null) {
+ throw new IllegalArgumentException();
+ }
+ int tabWidth=getTabWidth(options);
+ boolean isMixedMode= DefaultCodeFormatterConstants.MIXED.equals(options.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR));
+ if (isMixedMode) {
+ return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, tabWidth);
+ }
+ return tabWidth;
+ }
+
+ private static int getIntValue(Map options, String key, int def) {
+ try {
+ return Integer.parseInt((String) options.get(key));
+ } catch (NumberFormatException e) {
+ return def;
+ }
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/messages.properties b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/messages.properties
new file mode 100644
index 0000000..8fab89e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/formatter/messages.properties
@@ -0,0 +1,41 @@
+###############################################################################
+# Copyright (c) 2006 Ben Konrath
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Ben Konrath - initial implementation
+# IBM Corporation - Code review and integration
+###############################################################################
+CommandLineStart=Starting format job ...
+CommandLineDone=Done.
+CommandLineConfigFile=Configuration Name: {0}
+CommandLineFormatting=Formatting: {0}
+
+CommandLineUsage=Usage: eclipse -application org.eclipse.wst.jsdt.core.JavaCodeFormatter [ OPTIONS ] -config \n\
+\n\
+\ JavaScript source files and/or directories to format.\n\
+\ Only files ending with .js will be formatted in the given directory.\n\
+\ -config Use the formatting style from the specified properties file.\n\
+\ Refer to the help documentation to find out how to generate this file.\n\
+\n\
+\ OPTIONS:\n\
+\n\
+\ -help Display this message.\n\
+\ -quiet Only print error messages.\n\
+\ -verbose Be verbose about the formatting job.
+
+CommandLineErrorFile={0} does not exist. Please specify only valid JavaScript Source files.
+CommandLineErrorConfig=A problem occurred while reading the config file {0}.
+CommandLineErrorFileDir=You must specify at least one file or directory to format.
+CommandLineErrorQuietVerbose=You cannot use the options {0} and {1} together.
+CommandLineErrorNoConfigFile=No configuration file specified.
+
+CaughtException=Caught {0} : {1}
+ExceptionSkip= {0}\nSkipping File.
+
+ConfigFileReadingError=Error Reading config file.
+
+FormatProblem=The Eclipse formatter failed to format {0}. Skip the file.
\ No newline at end of file
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/DefaultInferrenceProvider.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/DefaultInferrenceProvider.java
new file mode 100644
index 0000000..5ff5330
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/DefaultInferrenceProvider.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+
+/**
+ * A default implementation of InferrenceProvider. It uses the default Inference engine.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class DefaultInferrenceProvider implements InferrenceProvider {
+
+ public static final String ID="org.eclipse.wst.jsdt.core.infer.DefaultInferrenceProvider";
+
+ public int applysTo(IInferenceFile scriptFile) {
+ char[] fileNameChars = scriptFile.getFileName();
+ if (fileNameChars!=null) {
+
+ String fileName = new String(fileNameChars);
+ if (fileName.indexOf("org.eclipse.wst.jsdt.core/libraries")>=0) {
+ return InferrenceProvider.ONLY_THIS;
+ }
+ }
+ return InferrenceProvider.MAYBE_THIS;
+ }
+
+ public IInferEngine getInferEngine() {
+ InferEngine engine = new InferEngine();
+ engine.inferenceProvider=this;
+ return engine;
+ }
+
+ public String getID() {
+ return ID;
+ }
+
+ public ResolutionConfiguration getResolutionConfiguration() {
+ return new ResolutionConfiguration();
+ }
+
+ public RefactoringSupport getRefactoringSupport() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/IInferEngine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/IInferEngine.java
new file mode 100644
index 0000000..cdf6e61
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/IInferEngine.java
@@ -0,0 +1,44 @@
+package org.eclipse.wst.jsdt.core.infer;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+
+/**
+ * Engine for inferring types from compilation unit.
+ *
+ * Clients may implement this interface but should expect some breakage by future releases.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ *
+ * @since 3.2
+ */
+public interface IInferEngine {
+
+ public final static char[] ANONYMOUS_PREFIX = {'_','_','_'};
+
+ public static final char[] ANONYMOUS_CLASS_ID= {'a','n','o','n','y','m','o','u','s'};
+
+ /**
+ * Initializes inference engine. Always called before {@link #setCompilationUnit()}
+ * to let engine prepare for next compilation unit.
+ */
+ void initialize();
+
+ /**
+ * Set compilation unit for processing.
+ */
+ void setCompilationUnit(CompilationUnitDeclaration parsedUnit);
+
+ /**
+ * Requests to perform type inference on provided compilation unit. Always called
+ * after {@link #setCompilationUnit(CompilationUnitDeclaration)}
+ */
+ void doInfer();
+
+ /**
+ * Provides inference options to the engine.
+ */
+ void initializeOptions(InferOptions inferOptions);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/IInferenceFile.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/IInferenceFile.java
new file mode 100644
index 0000000..36ac9a7
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/IInferenceFile.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+
+/**
+ * Representation of a file which can be inferrenced.
+ *
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IInferenceFile {
+ /**
+ * get the filename for the script if it can be determined
+ * @return the scripts file name, this could be null
+ */
+ char[] getFileName();
+
+ /**
+ * get the inference ID for the script if it is located in a container that specified an Inference ID
+ * @return the inference ID for the script, could be null
+ */
+ String getInferenceID();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/ImportRewriteSupport.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/ImportRewriteSupport.java
new file mode 100644
index 0000000..1f87197
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/ImportRewriteSupport.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+
+/**
+ * Support for extending the automatic import insertion mechanisms
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ImportRewriteSupport {
+
+ /**
+ * @return true if the import value matches a type name, false if the import value is a file path value
+ */
+ public boolean isImportMatchesType()
+ {
+ return true;
+ }
+
+ /**
+ * @return true if existing imports should be modified if necessary
+ */
+ public boolean isRewriteExisting()
+ {
+ return true;
+ }
+
+ /**
+ * @return the string which represents the import
+ */
+ public String getImportString(String importName, boolean isStatic, String lineDelim)
+ {
+ return null;
+ }
+
+ /**
+ * Find the starting position of an import when none already exist
+ * @return the starting position, -1 for default action
+ */
+ public int getImportStartPosition(JavaScriptUnit root) {
+ return -1;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java
new file mode 100644
index 0000000..2bd9a47
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferEngine.java
@@ -0,0 +1,2126 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import org.eclipse.wst.jsdt.core.ast.ASTVisitor;
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IAbstractFunctionDeclaration;
+import org.eclipse.wst.jsdt.core.ast.IAbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.core.ast.IAllocationExpression;
+import org.eclipse.wst.jsdt.core.ast.IArgument;
+import org.eclipse.wst.jsdt.core.ast.IAssignment;
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.core.ast.IFalseLiteral;
+import org.eclipse.wst.jsdt.core.ast.IFieldReference;
+import org.eclipse.wst.jsdt.core.ast.IFunctionCall;
+import org.eclipse.wst.jsdt.core.ast.IFunctionDeclaration;
+import org.eclipse.wst.jsdt.core.ast.IFunctionExpression;
+import org.eclipse.wst.jsdt.core.ast.IJsDoc;
+import org.eclipse.wst.jsdt.core.ast.ILocalDeclaration;
+import org.eclipse.wst.jsdt.core.ast.INumberLiteral;
+import org.eclipse.wst.jsdt.core.ast.IObjectLiteral;
+import org.eclipse.wst.jsdt.core.ast.IObjectLiteralField;
+import org.eclipse.wst.jsdt.core.ast.IProgramElement;
+import org.eclipse.wst.jsdt.core.ast.IReturnStatement;
+import org.eclipse.wst.jsdt.core.ast.IScriptFileDeclaration;
+import org.eclipse.wst.jsdt.core.ast.ISingleNameReference;
+import org.eclipse.wst.jsdt.core.ast.IStringLiteral;
+import org.eclipse.wst.jsdt.core.ast.IThisReference;
+import org.eclipse.wst.jsdt.core.ast.ITrueLiteral;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Reference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+/**
+ * The default inference engine.
+ *
+ * Clients may subclass this class but should expect some breakage by future releases.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferEngine extends ASTVisitor implements IInferEngine {
+
+ InferOptions inferOptions;
+ CompilationUnitDeclaration compUnit;
+ Context [] contexts=new Context[100];
+ int contextPtr=-1;
+ Context currentContext=new Context();
+ protected int passNumber=1;
+
+ boolean isTopLevelAnonymousFunction;
+ int anonymousCount=0;
+
+ public InferrenceProvider inferenceProvider;
+
+ public InferredType StringType=new InferredType(new char[]{'S','t','r','i','n','g'});
+ public InferredType NumberType=new InferredType(new char[]{'N','u','m','b','e','r'});
+ public InferredType BooleanType=new InferredType(new char[]{'B','o','o','l','e','a','n'});
+ public InferredType FunctionType=new InferredType(InferredType.FUNCTION_NAME);
+ public InferredType ArrayType=new InferredType(InferredType.ARRAY_NAME);
+ public InferredType VoidType=new InferredType(new char[]{'v','o','i','d'});
+ public InferredType ObjectType=new InferredType(InferredType.OBJECT_NAME);
+ public InferredType GlobalType=new InferredType(InferredType.GLOBAL_NAME);
+
+
+ public static HashtableOfObject WellKnownTypes=new HashtableOfObject();
+ {
+ WellKnownTypes.put(InferredType.OBJECT_NAME,null);
+ WellKnownTypes.put(InferredType.ARRAY_NAME,null);
+ WellKnownTypes.put(new char[]{'S','t','r','i','n','g'},null);
+ WellKnownTypes.put(new char[]{'N','u','m','b','e','r'},null);
+ WellKnownTypes.put(new char[]{'B','o','o','l','e','a','n'},null);
+ WellKnownTypes.put(InferredType.FUNCTION_NAME,null);
+ WellKnownTypes.put(new char[]{'D','a','t','e'},null);
+ WellKnownTypes.put(new char[]{'M','a','t','h'},null);
+ WellKnownTypes.put(new char[]{'R','e','g','E','x','p'},null);
+ WellKnownTypes.put(new char[]{'E','r','r','o','r'},null);
+ }
+
+
+
+ protected InferredType inferredGlobal=null;
+
+ static final char[] CONSTRUCTOR_ID={'c','o','n','s','t','r','u','c','t','o','r'};
+
+ static class Context
+ {
+ InferredType currentType;
+ IFunctionDeclaration currentMethod;
+
+ /** The current assignment.*/
+ IAssignment currentAssignment;
+
+ /** the current declaration */
+ ILocalDeclaration currentLocalDeclaration;
+ boolean isJsDocClass;
+
+ private HashtableOfObject definedMembers;
+
+ /*
+ * Parent context to provide chaining when searching
+ * for members in scope.
+ */
+ private Context parent = null;
+
+ /*
+ * Root context
+ */
+ Context(){}
+
+ /*
+ * Nested context
+ */
+ Context( Context parent )
+ {
+ this.parent = parent;
+
+ currentType = parent.currentType;
+ currentMethod = parent.currentMethod;
+ this.currentAssignment = parent.currentAssignment;
+ this.currentLocalDeclaration = parent.currentLocalDeclaration;
+ this.isJsDocClass=parent.isJsDocClass;
+ }
+
+ public Object getMember( char [] key ){
+
+ Object value = null;
+ if( definedMembers != null ){
+ value = definedMembers.get( key );
+ }
+
+ //chain lookup
+ if( value == null && parent != null ){
+ value = parent.getMember( key );
+ }
+
+ return value;
+ }
+
+ public void addMember( char [] key, Object member ){
+ if(key == null)
+ return;
+
+ if( definedMembers == null ){
+ definedMembers = new HashtableOfObject();
+ }
+
+ definedMembers.put( key, member );
+ }
+
+ public void setCurrentType(InferredType type)
+ {
+ this.currentType=type;
+ Context parentContext=this.parent;
+
+ while (parentContext!=null && parentContext.currentMethod==this.currentMethod)
+ {
+ parentContext.currentType=type;
+ parentContext=parentContext.parent;
+ }
+ }
+
+
+ }
+
+ private static boolean REPORT_INFER_TIME = false;
+
+ public InferEngine(InferOptions inferOptions)
+ {
+ this.inferOptions=inferOptions;
+ }
+
+ public InferEngine()
+ {
+ this.inferOptions=new InferOptions();
+ }
+
+
+ public void initialize()
+ {
+ this.contextPtr=-1;
+ this.currentContext=new Context();
+ this.passNumber=1;
+ this.isTopLevelAnonymousFunction=false;
+ this.anonymousCount=0;
+ this.inferredGlobal=null;
+ }
+
+ public void setCompilationUnit(CompilationUnitDeclaration scriptFileDeclaration) {
+ this.compUnit = scriptFileDeclaration;
+ buildDefinedMembers(scriptFileDeclaration.getStatements(),null);
+ }
+
+
+ public boolean visit(IFunctionCall functionCall) {
+ boolean visitChildren=handleFunctionCall(functionCall);
+ if (visitChildren)
+ {
+ if (this.contextPtr==-1 && functionCall.getReceiver() instanceof FunctionExpression)
+ this.isTopLevelAnonymousFunction=true;
+ }
+ return visitChildren;
+ }
+
+ public boolean visit(ILocalDeclaration localDeclaration) {
+ //add as a member of the current context
+ currentContext.addMember( localDeclaration.getName(), localDeclaration );
+
+ //create a new context for the local declaration
+ pushContext();
+ this.currentContext.currentLocalDeclaration = localDeclaration;
+
+ if (localDeclaration.getJsDoc()!=null)
+ {
+ Javadoc javadoc = (Javadoc)localDeclaration.getJsDoc();
+ createTypeIfNecessary(javadoc);
+ InferredAttribute attribute = null;
+ if (javadoc.memberOf!=null)
+ {
+ InferredType type = this.addType(javadoc.memberOf.getFullTypeName(),true);
+ int nameStart = localDeclaration.sourceStart();
+ attribute = type.addAttribute(localDeclaration.getName(), localDeclaration, nameStart);
+ handleAttributeDeclaration(attribute, localDeclaration.getInitialization());
+ if (localDeclaration.getInitialization()!=null)
+ attribute.initializationStart=localDeclaration.getInitialization().sourceStart();
+ attribute.type=type;
+ }
+
+ if (javadoc.returnType!=null)
+ {
+ InferredType type = this.addType(changePrimitiveToObject(javadoc.returnType.getFullTypeName()));
+ localDeclaration.setInferredType(type);
+ if (attribute!=null)
+ attribute.type=type;
+ }
+ }
+
+ // visit the function in case it defines a type
+ if(localDeclaration.getInitialization() instanceof IFunctionExpression) {
+ boolean keepVisiting = handleFunctionExpressionLocalDeclaration(localDeclaration);
+ if(!keepVisiting) {
+ return false;
+ }
+ }
+
+ if (localDeclaration.getInferredType()==null && localDeclaration.getInitialization()!=null)
+ {
+ if(localDeclaration.getInitialization() instanceof MessageSend) {
+ handleFunctionCall((IFunctionCall)localDeclaration.getInitialization(), (LocalDeclaration) localDeclaration);
+ } else {
+ localDeclaration.setInferredType(getTypeOf(localDeclaration.getInitialization()));
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.core.ast.ASTVisitor#endVisit(org.eclipse.wst.jsdt.core.ast.ILocalDeclaration)
+ */
+ public void endVisit(ILocalDeclaration localDeclaration) {
+ popContext();
+ }
+
+ private void createTypeIfNecessary(Javadoc javadoc) {
+ if (javadoc.memberOf!=null)
+ {
+ char [][]namespace={};
+ char[][] typeName = javadoc.memberOf.getTypeName();
+ if (javadoc.namespace!=null)
+ {
+ namespace=javadoc.namespace.getTypeName();
+ }
+ char [] name=CharOperation.concat(
+ CharOperation.concatWith(namespace, '.'),
+ CharOperation.concatWith(typeName, '.'),
+ '.');
+ this.currentContext.currentType=addType(name);
+ if (javadoc.extendsType!=null)
+ {
+ char[] superName = CharOperation.concatWith(javadoc.extendsType.getTypeName(),'.');
+ this.currentContext.currentType.superClass=addType(superName);
+ }
+ this.currentContext.isJsDocClass=true;
+
+ }
+
+ }
+
+ public boolean visit(IAssignment assignment) {
+ pushContext();
+ this.currentContext.currentAssignment = assignment;
+ IExpression assignmentExpression=assignment.getExpression();
+ if (handlePotentialType(assignment))
+ {
+
+ }
+ else if (assignmentExpression instanceof FunctionExpression)
+ {
+ boolean keepVisiting= handleFunctionExpressionAssignment(assignment);
+ if (!keepVisiting)
+ return false;
+ }
+ else if (assignmentExpression instanceof SingleNameReference && this.currentContext.currentType !=null &&
+ isThis(assignment.getLeftHandSide()))
+ {
+ ISingleNameReference snr=(ISingleNameReference)assignmentExpression;
+ Object object = this.currentContext.getMember( snr.getToken() );
+
+
+ IFieldReference fieldReference=(IFieldReference)assignment.getLeftHandSide();
+ char [] memberName = fieldReference.getToken();
+ InferredMember member = null;
+
+ int nameStart = fieldReference.sourceEnd() - memberName.length + 1;
+
+ /*
+ * this.foo = bar //bar is a function
+ */
+ if( object instanceof MethodDeclaration ){
+
+ MethodDeclaration method=(MethodDeclaration)object;
+ member = this.currentContext.currentType.addMethod(memberName, method, nameStart);
+
+ }
+ /*
+ * this.foo = bar //assume that bar is not a function and create a new attribute in the current type
+ */
+ else{
+
+ member = this.currentContext.currentType.addAttribute(memberName, assignment, nameStart);
+ handleAttributeDeclaration((InferredAttribute) member, assignment.getExpression());
+ if (((InferredAttribute) member).type == null)
+ ((InferredAttribute)member).type = getTypeOf( assignmentExpression );
+ }
+
+ //setting location
+ if( member != null ){
+ member.isStatic = false; //this is a not static member because it is being set on the this
+ }
+ }
+
+ /*
+ * foo = {};
+ */
+ else if ( assignmentExpression instanceof IObjectLiteral && assignment.getLeftHandSide() instanceof ISingleNameReference ){
+ IAbstractVariableDeclaration varDecl = getVariable( assignment.getLeftHandSide() );
+ if(varDecl == null) {
+ IAssignment existing = getAssignment(assignment.getLeftHandSide());
+ if(existing == null) {
+ //add as a member of the parent context (the current context is for the assignment)
+ currentContext.parent.addMember( getName(assignment.getLeftHandSide()), assignment );
+ }
+ }
+ if( varDecl != null ){
+ InferredType type = varDecl.getInferredType();
+
+ if( type == null ){
+ //create an anonymous type based on the ObjectLiteral
+ type = getTypeOf( assignmentExpression );
+
+ varDecl.setInferredType(type);
+
+ return true;
+ }
+ else
+ return false; //
+ } else {
+ IAssignment assignmentDecl = getAssignment(assignment.getLeftHandSide());
+ if( assignmentDecl != null ){
+ InferredType type = assignmentDecl.getInferredType();
+
+ if( type == null ){
+ //create an anonymous type based on the ObjectLiteral
+ type = getTypeOf( assignmentExpression );
+
+ assignmentDecl.setInferredType(type);
+
+ return true;
+ }
+ else
+ return false; //
+ }
+ }
+ }
+ /*
+ * foo.bar = {};
+ *
+ */
+ else if ( assignmentExpression instanceof IObjectLiteral && assignment.getLeftHandSide() instanceof FieldReference ){
+ FieldReference fRef = (FieldReference)assignment.getLeftHandSide();
+
+ boolean isKnownName=fRef.receiver.isThis() && isKnownType(fRef.getToken()) &&
+ (this.inferredGlobal!=null && this.inferredGlobal==this.currentContext.currentType);
+
+ if (isKnownName || (this.inferOptions.useAssignments && passNumber == 2 ))
+ {
+
+
+ InferredType receiverType = getInferredType( fRef.receiver );
+
+ if (receiverType==null && this.passNumber==2)
+ receiverType=getInferredType2(fRef.receiver );
+
+ if( receiverType != null ){
+ //check if there is an attribute already created
+
+ InferredAttribute attr = receiverType.findAttribute( fRef.getToken() );
+
+ //ignore if the attribute exists and has a type
+ if( !(attr != null && attr.type != null) ){
+
+ int nameStart = (int)(fRef.nameSourcePosition>>>32);
+
+ attr = receiverType.addAttribute(fRef.getToken(), assignment, nameStart);
+ handleAttributeDeclaration(attr, assignment.getExpression());
+ attr.type = getTypeOf( assignmentExpression );
+
+ if (isKnownName && attr.type.isAnonymous)
+ {
+ InferredType existingType = compUnit.findInferredType( fRef.getToken() ) ;
+ if (existingType!=null)
+ attr.type=existingType;
+ else
+ {
+ compUnit.inferredTypesHash.removeKey(attr.type.name);
+ attr.type.name=fRef.getToken();
+ compUnit.inferredTypesHash.put(attr.type.name, attr.type);
+ }
+ }
+
+
+ /*
+ * determine if static
+ *
+ * check if the receiver is a type
+ */
+ char [] possibleTypeName = constructTypeName( fRef.receiver );
+
+ if( receiverType.allStatic ||
+ (possibleTypeName != null && compUnit.findInferredType( possibleTypeName ) != null ))
+ attr.isStatic = true;
+ else
+ attr.isStatic = false;
+
+ return false; //done with this
+ }
+
+ }
+ }
+ }
+ else if ( assignmentExpression instanceof AllocationExpression &&
+ ((AllocationExpression)assignmentExpression).member instanceof FunctionExpression){
+ handleFunctionExpressionAssignment((Assignment)assignment);
+ }
+ else if ( assignmentExpression instanceof Assignment &&
+ ((Assignment)assignmentExpression).expression instanceof FunctionExpression){
+ handleFunctionExpressionAssignment((Assignment)assignment);
+ }
+ else
+ {
+ /*
+ * foo.bar = ? //? is not {} and not a function
+ */
+ if (this.inferOptions.useAssignments)
+ {
+ if( assignment.getLeftHandSide() instanceof FieldReference || assignment.getLeftHandSide() instanceof ArrayReference){
+
+ Reference ref = (Reference) assignment.getLeftHandSide();
+ Expression receiver = null;
+ char[] attName = null;
+ int nameStart = 0;
+ if(ref instanceof FieldReference) {
+ receiver = ((FieldReference)ref).receiver;
+ attName = ((FieldReference)ref).token;
+ nameStart=(int)(((FieldReference)ref).nameSourcePosition>>>32);
+ } else if(ref instanceof ArrayReference) {
+ if(((ArrayReference)ref).position instanceof StringLiteral) {
+ receiver = ((ArrayReference)ref).receiver;
+ attName = ((StringLiteral)((ArrayReference)ref).position).source();
+ nameStart = ((StringLiteral)((ArrayReference)ref).position).sourceStart + 1;
+ }
+ }
+
+ InferredType receiverType = getInferredType( receiver );
+ if (receiverType==null)
+ {
+ IFunctionDeclaration function = getDefinedFunction(receiver);
+ if (function!=null)
+ {
+ char [] typeName = constructTypeName(receiver);
+ if (typeName!=null)
+ receiverType=addType(typeName);
+ }
+ }
+ if (receiverType==null && this.passNumber==2)
+ receiverType=getInferredType2(receiver );
+
+ if( receiverType != null && attName != null){
+ //check if there is an attribute already created
+
+ InferredMethod method=null;
+ InferredAttribute attr = receiverType.findAttribute( attName );
+ if (attr==null)
+ method = receiverType.findMethod(attName, null);
+
+ //ignore if the attribute exists and has a type
+ if( (method==null && attr==null) || (method==null && attr != null && attr.type == null) ){
+
+
+// attr.type =
+ IFunctionDeclaration definedFunction=null;
+ InferredType exprType = getTypeOf( assignmentExpression );
+ if (exprType==null)
+ definedFunction = getDefinedFunction(assignmentExpression );
+
+ if (definedFunction!=null)
+ {
+ method = receiverType.addMethod(attName, definedFunction, nameStart);
+ method.isStatic=receiverType.allStatic;
+ }
+ else
+ {
+ int nameStart_ = nameStart;
+
+ attr = receiverType.addAttribute(attName, assignment, nameStart_);
+ handleAttributeDeclaration(attr, assignmentExpression);
+ attr.type=exprType;
+ /*
+ * determine if static
+ *
+ * check if the receiver is a type
+ */
+ char [] possibleTypeName = constructTypeName( receiver );
+
+ if( receiverType.allStatic||
+ (possibleTypeName != null && compUnit.findInferredType( possibleTypeName ) != null ))
+ attr.isStatic = true;
+ else
+ attr.isStatic = false;
+ }
+ return false; //done with this
+ }
+
+
+ }
+ }
+ }
+ }
+ return true; // do nothing by default, keep traversing
+ }
+
+ protected InferredType getInferredType2(IExpression fieldReceiver)
+ {
+ InferredType receiverType=null;
+ IAbstractVariableDeclaration var=getVariable(fieldReceiver);
+ if (var!=null)
+ {
+ receiverType=createAnonymousType(var);
+ }
+ else
+ {
+ if (this.inferredGlobal!=null && fieldReceiver instanceof ISingleNameReference)
+ {
+ char []name=((ISingleNameReference)fieldReceiver).getToken();
+ InferredAttribute attr=this.inferredGlobal.findAttribute(name);
+ if (attr!=null)
+ receiverType=attr.type;
+ }
+
+ }
+ return receiverType;
+ }
+
+ private InferredType createAnonymousType(IAbstractVariableDeclaration var) {
+
+ InferredType currentType = var.getInferredType();
+
+ if (currentType==null || !currentType.isAnonymous)
+ {
+ InferredType type=createAnonymousType(var.getName(), currentType);
+ var.setInferredType(type);
+ }
+ return var.getInferredType();
+ }
+
+ private InferredType createAnonymousType(IAssignment assignment) {
+
+ InferredType currentType = assignment.getInferredType();
+
+ if (currentType==null || !currentType.isAnonymous)
+ {
+ InferredType type=createAnonymousType(getName(assignment.getLeftHandSide()), currentType);
+ assignment.setInferredType(type);
+ }
+ return assignment.getInferredType();
+ }
+
+ protected InferredType createAnonymousType(char[] possibleTypeName, InferredType currentType) {
+ char []name;
+ if (this.isKnownType(possibleTypeName))
+ {
+ name=possibleTypeName;
+ }
+ else
+ {
+ char[] cs = String.valueOf(this.anonymousCount++).toCharArray();
+ name = CharOperation.concat(ANONYMOUS_PREFIX,possibleTypeName,cs);
+ }
+ InferredType type = addType(name,true);
+ type.isAnonymous=true;
+ if (currentType!=null)
+ type.superClass=currentType;
+ return type;
+ }
+ /*
+ * Creates an anonymous type based in the location in the document. This information is used
+ * to avoid creating duplicates because of the 2-pass nature of this engine.
+ */
+ private InferredType createAnonymousType( IObjectLiteral objLit ) {
+
+ if (objLit.getInferredType()!=null)
+ return objLit.getInferredType();
+ char []name = createAnonymousTypeName(objLit);
+
+ InferredType anonType = addType(name,true);
+ anonType.isAnonymous=true;
+ anonType.isObjectLiteral=true;
+ anonType.superClass = ObjectType;
+
+ anonType.sourceStart = objLit.sourceStart();
+ anonType.sourceEnd = objLit.sourceEnd();
+
+ populateType( anonType, objLit , false);
+
+ return anonType;
+ }
+
+
+ /**
+ * Creates an anonymous type name for the given {@link IASTNode}
+ *
+ * @param node create the anonymous type name off the location of this node
+ * @return an anonymous type name based off the given nodes location
+ */
+ protected static char[] createAnonymousTypeName(IASTNode node) {
+ char [] loc = (String.valueOf( node.sourceStart() ) + '_' + String.valueOf( node.sourceEnd() )).toCharArray();
+ return CharOperation.concat( ANONYMOUS_PREFIX, ANONYMOUS_CLASS_ID, loc );
+ }
+
+ /**
+ * handle the inferrencing for an assigment whose right hand side is a function expression
+ * @param the assignment AST node
+ * @return true if handled
+ */
+ protected boolean handleFunctionExpressionAssignment(IAssignment assignment)
+ {
+ IFunctionExpression functionExpression=null;
+ if (assignment.getExpression() instanceof IFunctionExpression)
+ functionExpression=(IFunctionExpression)assignment.getExpression();
+ else if (assignment.getExpression() instanceof IAllocationExpression)
+ functionExpression=(IFunctionExpression)((IAllocationExpression)assignment.getExpression()).getMember();
+ else if (assignment.getExpression() instanceof IAssignment)
+ functionExpression=(FunctionExpression)((IAssignment)assignment.getExpression()).getExpression();
+ MethodDeclaration methodDeclaration = functionExpression.getMethodDeclaration();
+
+ char [] possibleTypeName = constructTypeName( assignment.getLeftHandSide() );
+
+ InferredType type = null;
+ if( possibleTypeName != null )
+ {
+ type = compUnit.findInferredType( possibleTypeName );
+ if (type==null && isPossibleClassName(possibleTypeName))
+ {
+ type=addType(possibleTypeName,true);
+ }
+ if (type==null && methodDeclaration.getJsDoc()!=null && ((Javadoc)methodDeclaration.getJsDoc()).isConstructor)
+ {
+ type=addType(possibleTypeName,true);
+ handleJSDocConstructor(type, methodDeclaration, assignment.sourceStart());
+ }
+ }
+
+ if (type!=null) // isConstructor
+ {
+ if (this.inferOptions.useInitMethod)
+ {
+ this.currentContext.currentType=type;
+ type.isDefinition=true;
+ int nameStart = assignment.getLeftHandSide().sourceStart();
+ type.addConstructorMethod(type.name, methodDeclaration, nameStart);
+ type.updatePositions(nameStart, assignment.getExpression().sourceEnd());
+ }
+
+ }
+ else // could be method
+ {
+ if (assignment.getLeftHandSide() instanceof FieldReference || assignment.getLeftHandSide() instanceof ArrayReference)
+ {
+ Reference ref = (Reference) assignment.getLeftHandSide();
+ Expression receiver = null;
+ char[] methodName = null;
+ int nameStart = 0;
+ if(ref instanceof FieldReference) {
+ receiver = ((FieldReference)ref).receiver;
+ methodName = ((FieldReference)ref).token;
+ nameStart=(int)(((FieldReference)ref).nameSourcePosition>>>32);
+ } else if(ref instanceof ArrayReference) {
+ if(((ArrayReference)ref).position instanceof StringLiteral) {
+ receiver = ((ArrayReference)ref).receiver;
+ methodName = ((StringLiteral)((ArrayReference)ref).position).source();
+ nameStart = ((StringLiteral)((ArrayReference)ref).position).sourceStart + 1;
+ }
+ }
+
+ InferredType receiverType = getInferredType( receiver );
+
+ if( receiverType != null && methodName != null){
+
+ //check if there is a member method already created
+ InferredMethod method = receiverType.findMethod( methodName, methodDeclaration );
+
+ if( method == null ){
+ //create member method if it does not exist
+
+ method = receiverType.addMethod(methodName, methodDeclaration, nameStart);
+ receiverType.updatePositions(assignment.sourceStart(), assignment.sourceEnd()); // @GINO: not sure if necessary
+ receiverType.isDefinition=true;
+
+ /*
+ * determine if static
+ *
+ * check if the receiver is a type
+ */
+ char [] possibleInTypeName = constructTypeName( receiver );
+
+ if( receiverType.allStatic ||
+ (possibleInTypeName != null && compUnit.findInferredType( possibleInTypeName ) != null) )
+ method.isStatic = true;
+ else
+ method.isStatic = false;
+
+ return true; //keep visiting to get return type
+ }
+ else
+ return false; //no need to visit again
+
+ }
+ else if (this.passNumber==2 && methodName != null) // create anonymous class
+ {
+ receiverType = getInferredType2(receiver);
+ if (receiverType!=null)
+ {
+ InferredMethod method = receiverType.addMethod(methodName, methodDeclaration, nameStart);
+ method.isStatic=receiverType.isAnonymous;
+ receiverType.updatePositions(assignment.sourceStart(), assignment.sourceEnd());
+ }
+ }
+ }
+ else if (assignment.getLeftHandSide() instanceof SingleNameReference)
+ {
+ if(methodDeclaration.selector == null) {
+ methodDeclaration.potentialName = ((SingleNameReference)assignment.getLeftHandSide()).token;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Handle a local declaration who's right hand side is a function.
+ * Use case:
foo.bar.Test = function() { this.num = 42; }
+ *
+ * @param localDeclaration {@link ILocalDeclaration} to attempt to infer a type from
+ * @return true
if keep visiting, false
otherwise.
+ */
+ private boolean handleFunctionExpressionLocalDeclaration(ILocalDeclaration localDeclaration) {
+ boolean keepVisiting = true;
+ IFunctionExpression functionExpression=null;
+ IExpression expression = localDeclaration.getInitialization();
+ if (expression instanceof IFunctionExpression) {
+ functionExpression=(IFunctionExpression)expression;
+ } else if (expression instanceof IAllocationExpression) {
+ functionExpression=(IFunctionExpression)((IAllocationExpression)expression).getMember();
+ } else if (expression instanceof IAssignment) {
+ functionExpression=(FunctionExpression)((IAssignment)expression).getExpression();
+ }
+
+ MethodDeclaration methodDeclaration = functionExpression.getMethodDeclaration();
+ char [] possibleTypeName = localDeclaration.getName();
+
+ InferredType type = null;
+ if( possibleTypeName != null ) {
+ type = compUnit.findInferredType( possibleTypeName );
+ if (type == null && isPossibleClassName(possibleTypeName)) {
+ type = addType(possibleTypeName,true);
+ }
+ if (type == null && methodDeclaration.getJsDoc()!= null &&
+ ((Javadoc)methodDeclaration.getJsDoc()).isConstructor) {
+
+ type = addType(possibleTypeName,true);
+ handleJSDocConstructor(type, methodDeclaration, localDeclaration.sourceStart());
+ }
+ }
+
+ if (type!=null) { // isConstructor
+ if (this.inferOptions.useInitMethod) {
+ this.currentContext.currentType=type;
+ type.isDefinition=true;
+ int nameStart = localDeclaration.sourceStart();
+ type.addConstructorMethod(type.name, methodDeclaration, nameStart);
+ type.updatePositions(nameStart, localDeclaration.getInitialization().sourceEnd());
+ }
+
+ keepVisiting = false;
+ }
+ return keepVisiting;
+ }
+
+ /**
+ * @param assignment
+ * @return whether a type was not created for this assignment
+ */
+ protected boolean handlePotentialType(IAssignment assignment) {
+
+ IExpression lhs = assignment.getLeftHandSide();
+ if (lhs instanceof FieldReference) {
+ FieldReference fieldReference = (FieldReference) lhs;
+
+ /*
+ * foo.prototype = ?
+ */
+ if (fieldReference.isPrototype())
+ {
+ /*
+ * When encountering a prototype, we are going to assume that the
+ * receiver is a type.
+ *
+ * If the type had not been inferred, it will be added at this point
+ */
+ InferredType newType = null;
+ char [] possibleTypeName = constructTypeName( fieldReference.getReceiver() );
+ if( possibleTypeName != null )
+ newType = compUnit.findInferredType( possibleTypeName );
+ else
+ return true; //no type created
+
+
+ //create the new type if not found
+ if( newType == null ){
+ newType = addType( possibleTypeName ,true);
+ }
+ newType.isDefinition=true;
+
+// char[] typeName = getTypeName(fieldReference.receiver);
+// Object object = currentContext.definedMembers.get(typeName);
+//
+// if (object instanceof Argument)
+// return false;
+
+ newType.updatePositions(assignment.sourceStart(), assignment.sourceEnd());
+
+ /*
+ * foo.prototype = new ...
+ */
+ if (assignment.getExpression() instanceof IAllocationExpression)
+ {
+ //setting the super type
+ IAllocationExpression allocationExpression =(IAllocationExpression)assignment.getExpression();
+
+ InferredType superType = null;
+ char [] possibleSuperTypeName = constructTypeName( allocationExpression.getMember() );
+ if( possibleSuperTypeName != null ){
+ superType = compUnit.findInferredType( possibleSuperTypeName );
+
+ if( superType == null )
+ superType = addType( possibleSuperTypeName );
+
+ //check if it is set already because it might be set by jsdocs
+ if( newType.superClass == null )
+ newType.superClass = superType;
+ }
+
+ return true;
+ }
+ /*
+ * foo.prototype = {...}
+ */
+ else if( assignment.getExpression() instanceof IObjectLiteral ){
+ //rather than creating an anonymous type, is better just to set the members directly
+ //on newType
+ populateType( newType, (IObjectLiteral)assignment.getExpression(),false );
+
+ //check if it is set already because it might be set by jsdocs
+ if( newType.superClass == null )
+ newType.superClass = ObjectType;
+
+ return true;
+ }
+ }
+ /*
+ * foo.prototype.bar = ?
+ */
+ else if ( fieldReference.receiver.isPrototype() )
+ {
+
+ FieldReference prototype = (FieldReference) fieldReference.receiver;
+
+ InferredType newType = null;
+ char[] possibleTypeName = constructTypeName( prototype.receiver );
+ if( possibleTypeName != null )
+ newType = compUnit.findInferredType( possibleTypeName );
+ else
+ return true; //no type created
+
+ //create the new type if not found
+ if( newType == null ){
+ newType = addType( possibleTypeName );
+ }
+ newType.isDefinition = true;
+
+// char[] typeName = getTypeName(prototype.receiver);
+// Object receiverDef = currentContext.definedMembers.get(typeName);
+// if (receiverDef instanceof Argument)
+// return false;
+// InferredType newType = addType(typeName);
+// newType.isDefinition=true;
+
+ newType.updatePositions(assignment.sourceStart(), assignment.sourceEnd());
+
+ //prevent Object literal based anonymous types from being created more than once
+ if( passNumber == 1 && assignment.getExpression() instanceof IObjectLiteral ){
+ return false;
+ }
+
+ char[] memberName = fieldReference.token;
+ int nameStart= (int)(fieldReference.nameSourcePosition >>> 32);
+
+ InferredType typeOf = (assignment.getJsDoc() != null && assignment.getJsDoc() instanceof Javadoc && ((Javadoc) assignment.getJsDoc()).returnType != null) ? this.addType(changePrimitiveToObject(((Javadoc) assignment.getJsDoc()).returnType.getFullTypeName())) : getTypeOf(assignment.getExpression());
+ IFunctionDeclaration methodDecl=null;
+
+ if (typeOf==null || typeOf==FunctionType)
+ methodDecl=getDefinedFunction(assignment.getExpression());
+
+ if (methodDecl!=null)
+ {
+ InferredMember method = newType.addMethod(memberName, methodDecl, nameStart);
+ }
+ // http://bugs.eclipse.org/269053 - constructor property not supported in JSDT
+ else /*if (!CharOperation.equals(CONSTRUCTOR_ID, memberName))*/
+ {
+ InferredAttribute attribute = newType.addAttribute(memberName, assignment, nameStart);
+ handleAttributeDeclaration(attribute, assignment.getExpression());
+ attribute.initializationStart=assignment.getExpression().sourceStart();
+ if (attribute.type==null)
+ attribute.type=typeOf;
+ }
+ return true;
+ } else if(fieldReference.receiver instanceof IThisReference) {
+ InferredType newType = null;
+
+ IFunctionDeclaration parentMethod = this.currentContext.currentMethod;
+ IAssignment parentAssignment;
+ ILocalDeclaration parentLocalDeclaration;
+ char[] newTypeName = null;
+ /* if there is a current assignment and LHS is a function and that function
+ * is the current method then use the RHS as the type name
+ * else if there is a current local declaration and the LHS is a function and
+ * that function is the current method then use the RHS as the type name
+ * else if the parent method has a name use that as the type name
+ */
+ if(this.currentContext.parent != null &&
+ (parentAssignment = this.currentContext.parent.currentAssignment) != null &&
+ parentAssignment.getExpression() instanceof IFunctionExpression &&
+ ((IFunctionExpression)parentAssignment.getExpression()).getMethodDeclaration() == parentMethod) {
+
+ newTypeName = Util.getTypeName(parentAssignment.getLeftHandSide());
+ } else if(this.currentContext.parent != null &&
+ (parentLocalDeclaration = this.currentContext.parent.currentLocalDeclaration) != null &&
+ parentLocalDeclaration.getInitialization() instanceof IFunctionExpression &&
+ ((IFunctionExpression)parentLocalDeclaration.getInitialization()).getMethodDeclaration() == parentMethod) {
+
+ newTypeName = parentLocalDeclaration.getName();
+
+ }else if( parentMethod != null && parentMethod.getName() != null ) {
+ newTypeName = parentMethod.getName();
+ }
+
+ //if calculated new type name, use it to create a new type
+ if(newTypeName != null) {
+ newType = compUnit.findInferredType(newTypeName);
+ //create the new type if not found
+ if(newType == null) {
+ newType = addType(newTypeName);
+ }
+ } else {
+ return false; //no type to create
+ }
+
+ newType.isDefinition = true;
+
+ newType.updatePositions(assignment.sourceStart(), assignment.sourceEnd());
+
+ //prevent Object literal based anonymous types from being created more than once
+ if( passNumber == 1 && assignment.getExpression() instanceof IObjectLiteral ){
+ return false;
+ }
+
+ char[] memberName = fieldReference.token;
+ int nameStart= (int)(fieldReference.nameSourcePosition >>> 32);
+
+ InferredType typeOf = getTypeOf(assignment.getExpression());
+ IFunctionDeclaration methodDecl=null;
+
+ if (typeOf==null || typeOf==FunctionType)
+ methodDecl=getDefinedFunction(assignment.getExpression());
+
+ if (methodDecl!=null)
+ {
+ InferredMember method = newType.addMethod(memberName, methodDecl, nameStart);
+ }
+ // http://bugs.eclipse.org/269053 - constructor property not supported in JSDT
+ else /*if (!CharOperation.equals(CONSTRUCTOR_ID, memberName))*/
+ {
+ InferredAttribute attribute = newType.addAttribute(memberName, assignment, nameStart);
+ handleAttributeDeclaration(attribute, assignment.getExpression());
+ attribute.initializationStart=assignment.getExpression().sourceStart();
+ if (attribute.type==null)
+ attribute.type=typeOf;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the function referenced by the expression
+ *
+ * @param expression AST node
+ * @return the function or null
+ */
+ protected IFunctionDeclaration getDefinedFunction(IExpression expression)
+ {
+ if (expression instanceof SingleNameReference)
+ {
+ Object object = this.currentContext.getMember( ((SingleNameReference)expression).token );
+ if (object instanceof AbstractMethodDeclaration)
+ return (MethodDeclaration)object;
+ } else if (expression instanceof FunctionExpression)
+ return ((FunctionExpression)expression).methodDeclaration;
+ else if (expression instanceof FieldReference)
+ {
+ FieldReference fieldReference=(FieldReference)expression;
+ InferredType receiverType = getInferredType( fieldReference.receiver );
+ if (receiverType==null && passNumber==2)
+ receiverType=getInferredType2( fieldReference.receiver );
+ if (receiverType!=null)
+ {
+ InferredMethod method = receiverType.findMethod(fieldReference.token, null);
+ if (method!=null)
+ return method.getFunctionDeclaration();
+ }
+
+ }
+
+ return null;
+
+ }
+
+ protected InferredType getTypeOf(IExpression expression) {
+ if (expression instanceof IStringLiteral) {
+ return StringType;
+ }
+ else if (expression instanceof INumberLiteral) {
+ return NumberType;
+ }
+ else if (expression instanceof IAllocationExpression)
+ {
+ IAllocationExpression allocationExpression=(IAllocationExpression)expression;
+
+ InferredType type = null;
+ char [] possibleTypeName = constructTypeName( allocationExpression.getMember() );
+ if( possibleTypeName != null ){
+ type = compUnit.findInferredType( possibleTypeName );
+
+ if( type == null )
+ type = addType( possibleTypeName );
+
+ return type;
+ }
+ }
+ else if (expression instanceof ISingleNameReference)
+ {
+ IAbstractVariableDeclaration varDecl = getVariable( expression );
+ if( varDecl != null )
+ return varDecl.getInferredType();
+
+ if (this.inferredGlobal!=null)
+ {
+ InferredAttribute attribute = this.inferredGlobal.findAttribute(((ISingleNameReference)expression).getToken() );
+ if (attribute!=null)
+ return attribute.type;
+ }
+
+ }
+ else if (expression instanceof FieldReference)
+ {
+ FieldReference fieldReference=(FieldReference)expression;
+ if (fieldReference.receiver.isThis() && currentContext.currentType!=null)
+ {
+ InferredAttribute attribute = currentContext.currentType.findAttribute(fieldReference.getToken());
+ if (attribute!=null)
+ return attribute.type;
+ }
+ }
+ else if (expression instanceof ArrayInitializer)
+ {
+ ArrayInitializer arrayInitializer = (ArrayInitializer)expression;
+ boolean typeSet=false;
+ InferredType memberType=null;
+ if (arrayInitializer.expressions!=null)
+ for (int i = 0; i < arrayInitializer.expressions.length; i++) {
+ InferredType thisType = getTypeOf(arrayInitializer.expressions[i]);
+ if (thisType!=null)
+ {
+ if (!thisType.equals(memberType))
+ if (!typeSet)
+ memberType=thisType;
+ else
+ memberType=null;
+ typeSet=true;
+
+ }
+ }
+ if (memberType!=null)
+ {
+ InferredType type = new InferredType(InferredType.ARRAY_NAME);
+ type.referenceClass=memberType;
+ return type;
+ }
+ else
+ return ArrayType;
+ } else if (expression instanceof ITrueLiteral || expression instanceof IFalseLiteral) {
+ return BooleanType;
+ }
+ else if ( expression instanceof IObjectLiteral ){
+
+ //create an annonymous type based on the ObjectLiteral
+ InferredType type = createAnonymousType( (IObjectLiteral)expression);
+
+ //set the start and end
+ type.sourceStart = expression.sourceStart();
+ type.sourceEnd = expression.sourceEnd();
+
+ return type;
+
+
+ } else if ( expression instanceof IThisReference ){
+ return this.currentContext.currentType;
+ }
+ else if (expression instanceof Assignment)
+ return getTypeOf(((Assignment)expression).getExpression());
+ else if (expression instanceof FunctionExpression)
+ return FunctionType;
+ else if(expression instanceof UnaryExpression) {
+ return getTypeOf(((UnaryExpression)expression).expression);
+ } else if(expression instanceof BinaryExpression) {
+ BinaryExpression bExpression = (BinaryExpression) expression;
+ int operator = (bExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
+ switch(operator) {
+ case OperatorIds.MULTIPLY :
+ case OperatorIds.DIVIDE :
+ case OperatorIds.REMAINDER :
+ case OperatorIds.MINUS:
+ case OperatorIds.LEFT_SHIFT:
+ case OperatorIds.RIGHT_SHIFT:
+ return NumberType;
+ case OperatorIds.PLUS:
+ InferredType leftType = getTypeOf(bExpression.left);
+ InferredType rightType = getTypeOf(bExpression.right);
+ if(leftType != null && leftType.equals(StringType))
+ return StringType;
+ if(rightType != null && rightType.equals(StringType))
+ return StringType;
+ if(leftType == null || rightType == null)
+ return null;
+ if(leftType.equals(StringType) || rightType.equals(StringType)) {
+ return StringType;
+ } else if(leftType.equals(NumberType) && rightType.equals(NumberType)) {
+ return NumberType;
+ }
+ return null;
+ case OperatorIds.EQUAL_EQUAL:
+ case OperatorIds.EQUAL_EQUAL_EQUAL:
+ case OperatorIds.NOT_EQUAL:
+ case OperatorIds.NOT_EQUAL_EQUAL:
+ case OperatorIds.GREATER:
+ case OperatorIds.GREATER_EQUAL:
+ case OperatorIds.LESS:
+ case OperatorIds.LESS_EQUAL:
+ case OperatorIds.INSTANCEOF:
+ case OperatorIds.IN:
+ case OperatorIds.AND_AND:
+ case OperatorIds.OR_OR:
+ return BooleanType;
+ default:
+ return null;
+ }
+ }
+
+ return null;
+ }
+
+ protected void populateType(InferredType type, IObjectLiteral objLit, boolean isStatic) {
+ if (objLit.getInferredType()==null) {
+ objLit.setInferredType(type);
+ if (objLit.getFields() != null) {
+ for (int i = 0; i < objLit.getFields().length; i++) {
+ IObjectLiteralField field = objLit.getFields()[i];
+
+ char[] name = null;
+ int nameStart = -1;
+
+ if (field.getFieldName() instanceof SingleNameReference) {
+ SingleNameReference singleNameReference = (SingleNameReference) field.getFieldName();
+ name = singleNameReference.token;
+ nameStart = singleNameReference.sourceStart;
+ } else if (field.getFieldName() instanceof IStringLiteral) {
+ IStringLiteral stringLiteral = (IStringLiteral) field.getFieldName();
+ name = stringLiteral.source();
+ nameStart = stringLiteral.sourceStart();
+ } else
+ continue; //not supporting this case right now
+
+ Javadoc javaDoc = (Javadoc)field.getJsDoc();
+ InferredType returnType=null;
+ if (javaDoc!=null)
+ {
+ if (javaDoc.memberOf!=null)
+ {
+ char[] typeName = javaDoc.memberOf.getFullTypeName();
+ convertAnonymousTypeToNamed(type,typeName);
+ type.isDefinition=true;
+ }
+ else if (this.currentContext.isJsDocClass && javaDoc.property!=null)
+ {
+ if (type.isAnonymous )
+ {
+ InferredType previousType = this.currentContext.currentType;
+ if (previousType!=null)
+ {
+ copyAnonymousTypeToNamed(type,previousType);
+ objLit.setInferredType(type = this.currentContext.currentType = previousType);
+ }
+
+ }
+ }
+ if (javaDoc.returnType!=null)
+ {
+ returnType=this.addType(changePrimitiveToObject(javaDoc.returnType.getFullTypeName()));
+ }
+ }
+
+ //need to build the members of the annonymous inferred type
+ if (field.getInitializer() instanceof IFunctionExpression) {
+ IFunctionExpression functionExpression = (IFunctionExpression) field.getInitializer();
+ InferredMember method = type.addMethod(name,
+ functionExpression.getMethodDeclaration(), nameStart);
+ method.isStatic=isStatic;
+ if (javaDoc!=null)
+ {
+ functionExpression.getMethodDeclaration().modifiers=javaDoc.modifiers;
+ }
+ handleFunctionDeclarationArguments(functionExpression.getMethodDeclaration(),javaDoc);
+ if (returnType!=null && functionExpression.getMethodDeclaration().getInferredType() == null)
+ {
+ functionExpression.getMethodDeclaration().setInferredType(returnType);
+ }
+
+
+ } else //attribute
+ {
+ InferredAttribute attribute = type.findAttribute(name);
+ if (attribute == null) {
+ attribute = type.addAttribute(name, field.getInitializer(), nameStart);
+ handleAttributeDeclaration(attribute, field.getInitializer());
+ attribute.isStatic=isStatic;
+ //@GINO: recursion might not be the best idea
+ if (returnType!=null) {
+ attribute.type = returnType;
+ // apply (force) type onto OL initializer
+ if (field.getInitializer() instanceof ObjectLiteral) {
+ ((ObjectLiteral) field.getInitializer()).setInferredType(returnType);
+ }
+ }
+ else
+ attribute.type = getTypeOf(field.getInitializer());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void endVisit(IAssignment assignment) {
+ popContext();
+ }
+
+ protected boolean handleAttributeDeclaration(InferredAttribute attribute, IExpression initializer) {
+ return true;
+ }
+
+ protected boolean handleFunctionCall(IFunctionCall messageSend) {
+ return handleFunctionCall(messageSend, null);
+ }
+
+ protected boolean handleFunctionCall(IFunctionCall messageSend, LocalDeclaration assignmentExpression) {
+ return true;
+ }
+
+ public void endVisit(IReturnStatement returnStatement) {
+
+// if (currentContext.currentMethod!=null)
+// {
+// if (returnStatement.getExpression()!=null)
+// {
+//
+// InferredType type = getTypeOf(returnStatement.getExpression());
+//
+// if (currentContext.currentMethod.inferredType==VoidType)
+// currentContext.currentMethod.inferredType=type;
+// else if (type==null || !type.equals(currentContext.currentMethod.inferredType))
+// currentContext.currentMethod.inferredType=null;
+// }
+// }
+
+ }
+
+
+ public boolean visit(IReturnStatement returnStatement) {
+
+ if (currentContext.currentMethod!=null)
+ {
+ if (returnStatement.getExpression()!=null)
+ {
+
+ InferredType type = null;
+ IExpression expression = returnStatement.getExpression();
+ if (expression instanceof IObjectLiteral)
+ {
+ type = createAnonymousType( (ObjectLiteral)expression);
+
+ //set the start and end
+ type.sourceStart = expression.sourceStart();
+ type.sourceEnd = expression.sourceEnd();
+ }
+ else
+ type=getTypeOf(expression);
+
+ if (currentContext.currentMethod.getInferredType()==VoidType) {
+ currentContext.currentMethod.setInferredType(type);
+ } else {
+ /* If the return statement inferred type is null or
+ * the existing inferred return type and the statement return type are not equal and
+ * the return type is either not well known or is well known and the return type names are the same
+ *
+ * This logic is to cover the scenario where the return type is a known type but is from a
+ * different instance of the InferEngine
+ */
+ boolean shouldSetToAny = !((MethodDeclaration)currentContext.currentMethod).isInferredJsDocType();
+ if(type != null && shouldSetToAny) {
+ //get the name of the current methods inferred return type
+ String currentMethodInferredType = null;
+ if( this.currentContext.currentMethod.getInferredType() != null && this.currentContext.currentMethod.getInferredType().name != null) {
+ currentMethodInferredType = new String(this.currentContext.currentMethod.getInferredType().name);
+ }
+
+ boolean returnTypesEqual = type.equals(currentContext.currentMethod.getInferredType());
+ boolean returnTypeNamesEqual = (new String(type.name)).equals(currentMethodInferredType);
+ boolean returnTypeIsWellKnown = WellKnownTypes.containsKey(type.name);
+
+ shouldSetToAny = !returnTypesEqual && (!returnTypeIsWellKnown || !(returnTypeIsWellKnown && returnTypeNamesEqual));
+ }
+
+ if(shouldSetToAny) {
+ currentContext.currentMethod.setInferredType(null);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+
+ public void endVisit(IFunctionDeclaration methodDeclaration) {
+ popContext();
+ }
+
+ public boolean visit(IFunctionDeclaration methodDeclaration) {
+ pushContext();
+ if (this.isTopLevelAnonymousFunction && this.currentContext.currentType==null)
+ {
+ this.currentContext.currentType=addType(InferredType.GLOBAL_NAME,true);
+ this.inferredGlobal=this.currentContext.currentType;
+ }
+
+ this.isTopLevelAnonymousFunction=false;
+ char[] methodName = methodDeclaration.getName();
+ //if declaration didn't have name get name from inferred method if there is one
+ if(methodName == null && methodDeclaration.getInferredMethod() != null) {
+ methodName = methodDeclaration.getInferredMethod().name;
+ }
+
+ if (passNumber==1)
+ {
+ buildDefinedMembers((ProgramElement[])methodDeclaration.getStatements(),(Argument[])methodDeclaration.getArguments());
+ if (methodDeclaration.getJsDoc()!=null)
+ {
+ InferredMethod method=null;
+ Javadoc javadoc = (Javadoc)methodDeclaration.getJsDoc();
+ createTypeIfNecessary(javadoc);
+ if (javadoc.isConstructor)
+ {
+ InferredType type;
+ if (!this.currentContext.isJsDocClass && methodName!=null)
+ type = this.addType(methodName);
+ else
+ type=this.currentContext.currentType;
+ if (type!=null)
+ handleJSDocConstructor(type, methodDeclaration, methodDeclaration.sourceStart());
+ }
+ else if (javadoc.memberOf!=null)
+ {
+ InferredType type = this.addType(javadoc.memberOf.getFullTypeName(),true);
+ char [] name=methodName;
+ int nameStart = methodDeclaration.sourceStart();
+ if (name!=null)
+ method=type.addMethod(methodName, methodDeclaration, nameStart);
+ }
+ else if (javadoc.methodDef!=null && this.currentContext.isJsDocClass)
+ {
+ InferredType type=this.currentContext.currentType;
+ char[][] methName = javadoc.methodDef.getTypeName();
+ int nameStart = ((MethodDeclaration)methodDeclaration).sourceStart;
+ if (methName.length==1)
+ method=type.addMethod(methName[0], methodDeclaration, nameStart);
+ else
+ {
+ method=type.addMethod(methName[methName.length-1], methodDeclaration, nameStart);
+ method.isStatic=true;
+ }
+
+ }
+
+ if (javadoc.returnType!=null)
+ {
+ InferredType type = this.addType(changePrimitiveToObject(javadoc.returnType.getFullTypeName()));
+ methodDeclaration.setInferredType(type);
+ ((MethodDeclaration)methodDeclaration).bits |= ASTNode.IsInferredJsDocType;
+ }
+
+ }
+ handleFunctionDeclarationArguments((MethodDeclaration)methodDeclaration,(Javadoc)methodDeclaration.getJsDoc());
+ }
+ // check if this is a constructor
+ if (passNumber==2)
+ {
+
+ if (methodName!=null) {
+ InferredType type = compUnit
+ .findInferredType(methodName);
+ if (type != null) {
+ this.currentContext.currentType = type;
+ type.isDefinition = true;
+ int nameStart = methodDeclaration.sourceStart();
+ type.addConstructorMethod(methodName, methodDeclaration, nameStart);
+ }
+ }
+ }
+ this.currentContext.currentMethod=(MethodDeclaration)methodDeclaration;
+ if (methodDeclaration.getInferredMethod()!=null && methodDeclaration.getInferredMethod().inType!=null)
+ this.currentContext.currentType=methodDeclaration.getInferredMethod().inType;
+ if (methodDeclaration.getInferredType()==null)
+ methodDeclaration.setInferredType(VoidType);
+ return true;
+ }
+
+ protected void handleJSDocConstructor(InferredType type,IFunctionDeclaration methodDeclaration, int nameStart) {
+ Javadoc javadoc = (Javadoc)methodDeclaration.getJsDoc();
+ type.isDefinition=true;
+ type.addConstructorMethod(type.name, methodDeclaration, nameStart);
+
+ if (javadoc.extendsType!=null)
+ {
+ InferredType superType=this.addType(javadoc.extendsType.getFullTypeName());
+ type.superClass=superType;
+ }
+
+ }
+
+ protected void handleFunctionDeclarationArguments(IFunctionDeclaration methodDeclaration, IJsDoc jsdoc) {
+ if (jsdoc==null || !(jsdoc instanceof Javadoc))
+ return;
+ Javadoc javadoc = (Javadoc) jsdoc;
+
+ IArgument[] arguments = methodDeclaration.getArguments();
+ if (arguments!=null)
+ for (int i = 0; i < arguments.length; i++) {
+ if (arguments[i].getInferredType() != null)
+ continue;
+
+ JavadocSingleNameReference param = javadoc.findParam(arguments[i].getName());
+ if (param!=null)
+ {
+ if (param.types!=null)
+ {
+ char []name={};
+ for (int j = 0; j < param.types.length; j++) {
+ //char []typeName=param.types[j].getFullTypeName();
+ //make sure we are using the type version of Boolean, even if the user entered boolean as the JSdoc type.
+ char []typeName=changePrimitiveToObject(param.types[j].getFullTypeName());
+ if (j==0)
+ name=typeName;
+ else
+ {
+ name=CharOperation.append(name, '|');
+ name=CharOperation.concat(name, typeName);
+ }
+ }
+ InferredType paramType=this.addType(name);
+ arguments[i].setInferredType(paramType);
+ }
+ }
+ }
+ }
+
+
+
+ public boolean visit(
+ IAllocationExpression allocationExpression) {
+
+ InferredType type = null;
+ char [] possibleTypeName = constructTypeName( allocationExpression.getMember() );
+ if( possibleTypeName != null ){
+ type = compUnit.findInferredType( possibleTypeName );
+
+ if( type == null )
+ type = addType( possibleTypeName ); //creating type
+ }
+ return true;
+ }
+
+
+ public void endVisit(IObjectLiteralField field) {
+// if (field.getJsDoc()!=null)
+// {
+// Javadoc javaDoc = (Javadoc)field.getJsDoc();
+// InferredType inClass=this.currentContext.currentType;
+// char [] name=null;
+// int nameStart=-1;
+// InferredType returnType=null;
+//// boolean isFunction=field.initializer instanceof FunctionExpression;
+// if (field.getFieldName() instanceof SingleNameReference)
+// {
+// SingleNameReference singleNameReference=(SingleNameReference)field.getFieldName();
+// name=singleNameReference.token;
+// nameStart=singleNameReference.sourceStart;
+// }
+// if (javaDoc.memberOf!=null)
+// {
+// char[] typeName = javaDoc.memberOf.getFullTypeName();
+// convertAnonymousTypeToNamed(inClass,typeName);
+// inClass.isDefinition=true;
+// }
+// else if (this.currentContext.isJsDocClass && javaDoc.property!=null)
+// {
+// if (this.currentContext.currentType.isAnonymous && this.currentContext.parent!=null)
+// {
+// InferredType previousType = this.currentContext.parent.currentType;
+// if (previousType!=null)
+// {
+// copyAnonymousTypeToNamed(inClass,previousType);
+// this.currentContext.currentType=previousType;
+// }
+//
+// }
+// }
+// if (javaDoc.returnType!=null)
+// {
+// returnType=this.addType(javaDoc.returnType.getFullTypeName());
+// }
+//
+// if (inClass!=null && name!=null)
+// {
+// if (field.getInitializer() instanceof FunctionExpression) {
+// FunctionExpression functionExpression = (FunctionExpression) field.getInitializer();
+// InferredMember method = inClass.addMethod(name, functionExpression.methodDeclaration,false);
+// method.nameStart=nameStart;
+// functionExpression.methodDeclaration.modifiers=javaDoc.modifiers;
+// if (returnType!=null)
+// {
+// functionExpression.methodDeclaration.inferredType=returnType;
+// }
+//// else
+//// method.inferredType=functionExpression.methodDeclaration.inferredType;
+// }
+// else //attribute
+// {
+// InferredAttribute attribute = inClass.addAttribute(name, field.getFieldName());
+// attribute.nameStart=field.getFieldName().sourceStart();
+// if (returnType!=null)
+// attribute.type=returnType;
+// }
+// }
+//
+// }
+// //no jsdoc
+// else{
+//
+// if( field.getInitializer() instanceof ObjectLiteral ){
+//
+// }
+//
+//
+// }
+ }
+
+ private void copyAnonymousTypeToNamed(InferredType inClass,
+ InferredType toType) {
+ if (toType==null)return;
+
+ compUnit.inferredTypesHash.removeKey(inClass.name);
+ if (inClass.methods!=null)
+ {
+ toType.methods.addAll(inClass.methods);
+// else
+// toType.methods=inClass.methods;
+
+ }
+ if (inClass.attributes!=null)
+ {
+ for (int i = 0; i < inClass.numberAttributes; i++) {
+ toType.addAttribute(inClass.attributes[i]);
+ }
+ }
+
+
+ }
+
+ private void convertAnonymousTypeToNamed(InferredType inClass, char[] typeName) {
+ if (inClass.isAnonymous)
+ {
+ inClass.isAnonymous=false;
+ compUnit.inferredTypesHash.removeKey(inClass.name);
+ inClass.name=typeName;
+ compUnit.inferredTypesHash.put(typeName,inClass);
+
+ }
+
+ }
+
+ protected boolean isMatch(IExpression expr,char[] [] names, int index)
+ {
+ char [] matchName=names[index];
+ if (expr instanceof SingleNameReference) {
+ SingleNameReference snr = (SingleNameReference) expr;
+ return CharOperation.equals(snr.token, matchName);
+ }
+ else if (expr instanceof FieldReference && names.length>1 && index>0) {
+ FieldReference fieldReference = (FieldReference) expr;
+ if (CharOperation.equals(fieldReference.token, matchName))
+ return isMatch(fieldReference.receiver, names, index-1);
+
+ }
+ return false;
+ }
+
+ protected boolean isFunction(IFunctionCall messageSend,String string) {
+ String []names=string.split("\\."); //$NON-NLS-1$
+ char [] functionName=names[names.length-1].toCharArray();
+ if (!CharOperation.equals(functionName, messageSend.getSelector()))
+ return false;
+
+ char [][]namesChars=new char[names.length][];
+ for (int i = 0; i < namesChars.length; i++) {
+ namesChars[i]=names[i].toCharArray();
+ }
+ if (names.length>1)
+ return isMatch(messageSend.getReceiver(), namesChars, namesChars.length-2);
+ return true;
+ }
+
+ protected boolean isFunction(IFunctionCall messageSend,char [][]names) {
+ char [] functionName=names[names.length-1];
+ if (!CharOperation.equals(functionName, messageSend.getSelector()))
+ return false;
+
+ if (names.length>1)
+ return isMatch(messageSend.getReceiver(), names, names.length-2);
+ return true;
+ }
+
+
+ public void doInfer()
+ {
+ try {
+ long time0 = 0;
+ if (REPORT_INFER_TIME) {
+ time0 = System.currentTimeMillis();
+ }
+
+ compUnit.traverse(this );
+ passNumber=2;
+ compUnit.traverse(this );
+ for (int i = 0; i < compUnit.numberInferredTypes; i++) {
+ if (compUnit.inferredTypes[i].sourceStart<0)
+ compUnit.inferredTypes[i].sourceStart=0;
+ }
+
+ if (REPORT_INFER_TIME) {
+ long time = System.currentTimeMillis() - time0;
+ System.err.println(getClass().getName() + " inferred " + new String(compUnit.getFileName()) + " in " + time + "ms");
+ }
+ this.compUnit=null;
+
+ } catch (RuntimeException e) {
+ org.eclipse.wst.jsdt.internal.core.util.Util.log(e, "error during type inferencing");
+ }
+}
+
+ protected InferredType addType(char[] className) {
+ return addType(className,false);
+ }
+
+ /**
+ * Create a new inferred type with the given name
+ *
+ * @param className the name of the inferred type
+ * @param isDefinition true if this unit defines the type
+ * @return new Inferred type
+ */
+ protected InferredType addType(char[] className, boolean isDefinition) {
+ InferredType type = compUnit.addType(className, isDefinition, this.inferenceProvider.getID());
+
+ return type;
+ }
+
+ protected final void pushContext()
+ {
+ Context newContext = new Context( currentContext );
+ contexts[++contextPtr] = currentContext;
+ currentContext = newContext;
+
+ }
+
+ protected final void popContext()
+ {
+ currentContext = contexts[contextPtr];
+ contexts[contextPtr--] = null;
+ }
+
+ protected final boolean isInNamedMethod()
+ {
+ return this.currentContext.currentMethod!=null && this.currentContext.currentMethod.getName()!=null;
+ }
+
+
+ /**
+ * Finds a Var Declaration on the context from the name represented with the expression
+ *
+ * Currently, only SNR are supported
+ */
+ protected IAbstractVariableDeclaration getVariable(IExpression expression)
+ {
+ char [] name=null;
+
+ if (expression instanceof ISingleNameReference)
+ name = ((ISingleNameReference) expression).getToken();
+ else if (expression instanceof IFieldReference)
+ name = ((IFieldReference) expression).getToken();
+ if (name!=null)
+ {
+ Object var = this.currentContext.getMember( name );
+ if (var instanceof IAbstractVariableDeclaration)
+ return (IAbstractVariableDeclaration)var;
+
+ }
+ return null;
+
+ }
+
+ /**
+ * Finds a assignment on the context from the name represented with the expression
+ *
+ * Currently, only SNR are supported
+ */
+ protected IAssignment getAssignment(IExpression expression)
+ {
+ char [] name=null;
+
+ if (expression instanceof ISingleNameReference)
+ name = ((ISingleNameReference) expression).getToken();
+ else if (expression instanceof IFieldReference)
+ name = ((IFieldReference) expression).getToken();
+ if (name!=null)
+ {
+ Object assignment = this.currentContext.getMember( name );
+ if (assignment instanceof IAssignment)
+ return (IAssignment)assignment;
+
+ }
+ return null;
+
+ }
+
+ /**
+ * Finds a Function Declaration on the context from the name represented with the expression
+ *
+ * Currently, only SNR are supported
+ */
+ protected IAbstractFunctionDeclaration getFunction(IExpression expression)
+ {
+ char [] name=null;
+
+ if (expression instanceof ISingleNameReference)
+ name = ((ISingleNameReference) expression).getToken();
+ else if (expression instanceof IFieldReference)
+ name = ((IFieldReference) expression).getToken();
+ if (name!=null)
+ {
+ Object method = this.currentContext.getMember( name );
+ if (method instanceof IAbstractFunctionDeclaration)
+ return (IAbstractFunctionDeclaration)method;
+
+ }
+ return null;
+ }
+
+ private void buildDefinedMembers(IProgramElement[] statements, IArgument[] arguments) {
+
+ if (arguments!=null)
+ {
+ for (int i = 0; i < arguments.length; i++) {
+ this.currentContext.addMember( arguments[i].getName(), arguments[i] );
+ }
+ }
+ if (statements!=null)
+ {
+ for (int i = 0; i < statements.length; i++) {
+ if (statements[i] instanceof ILocalDeclaration) {
+ ILocalDeclaration local = (ILocalDeclaration) statements[i];
+ this.currentContext.addMember( local.getName(), local );
+ }
+ else if (statements[i] instanceof IAbstractFunctionDeclaration) {
+ IAbstractFunctionDeclaration method = (IAbstractFunctionDeclaration) statements[i];
+ if (method.getName()!=null)
+ this.currentContext.addMember( method.getName(), method );
+ }
+ }
+ }
+ }
+
+ private static boolean isThis(IExpression expression)
+ {
+ if (expression instanceof FieldReference && ((FieldReference)expression).receiver.isThis())
+ return true;
+ return false;
+ }
+
+ /*
+ * This method is used to determined the inferred type of a LHS Expression.
+ *
+ * It could return null.
+ *
+ * a.b.c
+ */
+ private InferredType getInferredType( Expression expression ){
+
+ InferredType type = null;
+
+ /*
+ * this
+ */
+ if( expression instanceof IThisReference ){
+ if (this.passNumber==2 && this.currentContext.currentType==null)
+ {
+ char [] possibleTypeName={'g','l','o','b','a','l'};
+ if (this.currentContext.currentMethod!=null)
+ possibleTypeName=this.currentContext.currentMethod.getName();
+ this.currentContext.setCurrentType(createAnonymousType(possibleTypeName, null));
+ }
+
+ type = this.currentContext.currentType;
+ }
+ /*
+ * foo (could be a Type name or a reference to a variable)
+ */
+ else if( expression instanceof SingleNameReference ){
+ char [] possibleTypeName = constructTypeName( expression );
+
+ if( possibleTypeName != null ){
+ //search the defined types in the context
+ type = compUnit.findInferredType( possibleTypeName );
+
+ if (type==null)
+ {
+ if (WellKnownTypes.containsKey(possibleTypeName))
+ {
+ type = addType(possibleTypeName,true);
+ }
+ else if (/*this.passNumber==2 && */this.isKnownType(possibleTypeName))
+ {
+ type = addType(possibleTypeName,true);
+// if (type!=null)
+// {
+// AbstractVariableDeclaration varDecl = getVariable( (expression) );
+//
+// if( varDecl != null ){
+// varDecl.inferredType=type;
+// }
+//
+// }
+ }
+
+ }
+
+
+ /*
+ * There is no match for a type with the name, check if the name refers to
+ * var decl and return its type
+ */
+ if( type == null ){
+
+ IAbstractVariableDeclaration varDecl = getVariable( expression );
+
+ if( varDecl != null ){
+ type = varDecl.getInferredType(); //could be null
+ if (type!=null && !type.isAnonymous) {
+ if(varDecl.getInitialization() instanceof IAllocationExpression && !type.isFunction()) {
+ type = createAnonymousType(varDecl);
+ } else {
+ InferredType superType = type;
+ type = addType(varDecl.getName(), true);
+ type.superClass = superType;
+ }
+ type.updatePositions(varDecl.sourceStart(), varDecl.sourceEnd());
+ }
+
+ } else {
+ IAssignment assignment = getAssignment(expression);
+ if(assignment != null) {
+ type = assignment.getInferredType(); //could be null
+ if (type!=null && !type.isAnonymous) {
+ if(assignment.getExpression() instanceof IAllocationExpression && !type.isFunction()) {
+ type = createAnonymousType(assignment);
+ } else {
+ InferredType superType = type;
+ type = addType(getName(assignment.getLeftHandSide()), true);
+ type.superClass = superType;
+ }
+ type.updatePositions(assignment.sourceStart(), assignment.sourceEnd());
+ }
+ }
+ }
+
+ }
+ }
+ }
+ /*
+ * foo.bar.xxx...
+ */
+ else if( expression instanceof FieldReference ){
+ char[] possibleTypeName = constructTypeName(expression);
+
+ if (possibleTypeName != null)
+ // search the defined types in the context
+ type = compUnit.findInferredType(possibleTypeName);
+
+ if (type==null && isPossibleClassName(possibleTypeName))
+ {
+ type = addType(possibleTypeName,true);
+ }
+
+ /*
+ * Continue the search by trying to resolve further down the name
+ * because this token of the field reference could be a member of a
+ * type or instance of a type
+ */
+ if (type == null) {
+ FieldReference fRef = (FieldReference) expression;
+
+ // this
+ InferredType parentType = getInferredType(fRef.receiver);
+
+ if (parentType != null) {
+ // check the members and return type
+ InferredAttribute typeAttribute = parentType
+ .findAttribute(fRef.token);
+
+ if (typeAttribute != null) {
+ type = typeAttribute.type;
+ if (type != null && !type.isAnonymous) {
+ if (possibleTypeName==null)
+ possibleTypeName=typeAttribute.name;
+ type = createAnonymousType(possibleTypeName, type);
+ typeAttribute.type = type;
+ }
+ }
+ }
+ }
+
+ }
+
+ return type;
+ }
+
+
+
+ protected boolean isKnownType(char[] possibleTypeName) {
+ return false;
+ }
+
+ /*
+ * For SNR it returns the name
+ * For FR it construct a Qualified name separated by '.'
+ *
+ * If at any point it hits a portion of the Field reference that is
+ * not supported (such as a function call, a prototype, or this )
+ */
+ protected final char [] constructTypeName( IExpression expression ){
+
+ return Util.getTypeName( expression );
+ }
+
+ public boolean visit(IObjectLiteral literal) {
+ if (this.passNumber==1 && literal.getInferredType()==null)
+ createAnonymousType((ObjectLiteral)literal);
+ pushContext();
+ this.currentContext.currentType=literal.getInferredType();
+ return true;
+ }
+
+ public void endVisit(IObjectLiteral literal) {
+ popContext();
+ }
+
+
+ /**
+ * Overriden by client who wish to update the infer options
+ *
+ * @param options
+ */
+ public void initializeOptions(InferOptions options) {
+ }
+
+ protected boolean isPossibleClassName(char[]name)
+ {
+ return false;
+ }
+
+ /**
+ * Get the Script file this inferrence is being done on
+ *
+ * @return
+ */
+ public IScriptFileDeclaration getScriptFileDeclaration()
+ {
+ return this.compUnit;
+ }
+
+ public InferredType findDefinedType(char [] className)
+ {
+ return compUnit.findInferredType(className);
+ }
+
+ protected char[] changePrimitiveToObject(char[] name) {
+ //Changes the first character of the name of the primitive types to uppercase. This will allow future reference to the object wrapper instead of the primitive type.
+ if(CharOperation.equals(name, TypeConstants.BOOLEAN, false)) //$NON-NLS-1$
+ return BooleanType.getName();
+ return name;
+ }
+
+ private char[] getName(IExpression expression) {
+ if (expression instanceof ISingleNameReference)
+ return ((ISingleNameReference) expression).getToken();
+ else if (expression instanceof IFieldReference)
+ return ((IFieldReference) expression).getToken();
+ return null;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferOptions.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferOptions.java
new file mode 100644
index 0000000..52169f9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferOptions.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ *
+ * Inference Options
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferOptions {
+
+ public static final String OPTION_UseAssignments = "org.eclipse.wst.jsdt.core.infer.useAssignments"; //$NON-NLS-1$
+ public static final String OPTION_UseInitMethod = "org.eclipse.wst.jsdt.core.infer.useInitMethod"; //$NON-NLS-1$
+ public static final String OPTION_SaveArgumentComments = "org.eclipse.wst.jsdt.core.infer.saveArgumentComments"; //$NON-NLS-1$
+ public static final String OPTION_DocLocation = "org.eclipse.wst.jsdt.core.infer.docLocation"; //$NON-NLS-1$
+
+
+ public static final int DOC_LOCATION_BEFORE=1;
+ public static final int DOC_LOCATION_AFTER=2;
+
+
+ // tags used to recognize tasks in comments
+ public char[][] systemClassMethod = null;
+
+ /**
+ * Set to true var types are inferred based on assigments
+ */
+ public boolean useAssignments=true;
+
+ public boolean useInitMethod;
+ public String engineClass;
+ public boolean saveArgumentComments;
+ public int docLocation=DOC_LOCATION_BEFORE;
+
+
+
+
+ /**
+ * Initializing the compiler options with defaults
+ */
+ public InferOptions(){
+ // use default options
+ setDefaultOptions();
+ }
+
+ /**
+ * Initializing the compiler options with external settings
+ * @param settings
+ */
+ public InferOptions(Map settings){
+
+ if (settings == null) return;
+ set(settings);
+ }
+
+ public void setDefaultOptions()
+ {
+ this.useAssignments=true;
+ this.useInitMethod=true;
+ this.saveArgumentComments=true;
+ }
+
+ public Map getMap() {
+ Map optionsMap = new HashMap(30);
+ optionsMap.put(OPTION_UseAssignments, this.useAssignments ? "true":"false"); //$NON-NLS-1$ //$NON-NLS-2$
+ optionsMap.put(OPTION_UseInitMethod, this.useInitMethod ? "true":"false"); //$NON-NLS-1$ //$NON-NLS-2$
+ optionsMap.put(OPTION_SaveArgumentComments, this.saveArgumentComments ? "true":"false"); //$NON-NLS-1$ //$NON-NLS-2$
+ optionsMap.put(OPTION_DocLocation, String.valueOf(this.docLocation)); //$NON-NLS-1$ //$NON-NLS-2$
+ return optionsMap;
+ }
+
+
+ public void set(Map optionsMap) {
+
+ Object optionValue;
+ if ((optionValue = optionsMap.get(OPTION_UseAssignments)) != null) {
+ this.useAssignments="true".equals(optionValue) ; //$NON-NLS-1$
+ }
+ if ((optionValue = optionsMap.get(OPTION_UseInitMethod)) != null) {
+ this.useInitMethod="true".equals(optionValue) ; //$NON-NLS-1$
+ }
+ if ((optionValue = optionsMap.get(OPTION_SaveArgumentComments)) != null) {
+ this.saveArgumentComments="true".equals(optionValue) ; //$NON-NLS-1$
+ }
+ if ((optionValue = optionsMap.get(OPTION_DocLocation)) != null) {
+ this.docLocation= Integer.parseInt((String)optionValue) ; //$NON-NLS-1$
+ }
+ }
+
+ public String toString() {
+
+ StringBuffer buf = new StringBuffer("InferOptions:"); //$NON-NLS-1$
+ buf.append("\n\t- use assignments: ").append( this.useAssignments ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ buf.append("\n\t- use initialization method : ").append( this.useInitMethod ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return buf.toString();
+ }
+
+
+ public InferEngine createEngine()
+ {
+ if (engineClass!=null)
+ {
+ try {
+ InferEngine engine= (InferEngine) Class.forName(engineClass).newInstance();
+ engine.inferOptions=this;
+ return engine;
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ //TODO: implement something
+ }
+ }
+ return new InferEngine(this);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredAttribute.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredAttribute.java
new file mode 100644
index 0000000..1b963ca
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredAttribute.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+
+
+/**
+ *
+ * This represents an inferred attribute.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferredAttribute extends InferredMember{
+
+ public FieldBinding binding;
+ public int initializationStart=-1;
+
+ /**
+ * The type of this attribute
+ */
+ public InferredType type;
+ public ASTNode node;
+ public int modifiers;
+
+ /**
+ * Creates an attribute with this name in the given inferred type. This
+ * method is discouraged in favor of supplying the ASTNode which declared
+ * the attribute.
+ */
+ public InferredAttribute(char [] name, InferredType inType, int start, int end)
+ {
+ this.name=name;
+ this.inType = inType;
+ this.sourceStart=start;
+ this.sourceEnd=end;
+ }
+
+
+ /**
+ * @param name
+ * @param inferredType the type to which this attribute belongs
+ * @param definer
+ */
+ public InferredAttribute(char[] name, InferredType inferredType, IASTNode definer) {
+ this(name, inferredType, definer.sourceStart(), definer.sourceEnd());
+ node = (ASTNode) definer;
+ }
+
+
+ public StringBuffer print(int indent, StringBuffer output)
+ {
+ String modifier=(isStatic)? "static ":""; //$NON-NLS-1$ //$NON-NLS-2$
+ printIndent(indent, output).append(modifier);
+ if (type!=null)
+ type.dumpReference(output);
+ else
+ output.append("??"); //$NON-NLS-1$
+ output.append(" ").append(name); //$NON-NLS-1$
+ return output;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredMember.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredMember.java
new file mode 100644
index 0000000..6efbdc5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredMember.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+
+
+/**
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class InferredMember extends ASTNode{
+
+ /**
+ * The name of this member
+ */
+ public char [] name;
+ /**
+ * The type to which this member belongs
+ */
+ public InferredType inType;
+ /**
+ * The source offset at which the name of this member begins
+ */
+ public int nameStart;
+ public boolean isStatic = false;
+
+ public boolean isInferred()
+ {
+ return true;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredMethod.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredMethod.java
new file mode 100644
index 0000000..5bfd63b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredMethod.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import org.eclipse.wst.jsdt.core.ast.IFunctionDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+
+
+/**
+ *
+ * This represents an inferred method
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferredMethod extends InferredMember{
+
+ private MethodDeclaration methodDeclaration;
+
+ public boolean isConstructor;
+ public MethodBinding methodBinding;
+ public InferredMethod(char [] name, IFunctionDeclaration functionDeclaration, InferredType inType )
+ {
+ this.methodDeclaration=(MethodDeclaration)functionDeclaration;
+ this.name=name;
+ this.inType = inType;
+ this.sourceStart=methodDeclaration.sourceStart;
+ this.sourceEnd=methodDeclaration.sourceEnd;
+ }
+
+ public IFunctionDeclaration getFunctionDeclaration()
+ {
+ return methodDeclaration;
+ }
+
+ public StringBuffer print(int indent, StringBuffer output)
+ {
+ String modifier=(isStatic)? "static ":""; //$NON-NLS-1$ //$NON-NLS-2$
+ printIndent(indent, output).append(modifier);
+ if (!isConstructor)
+ {
+ if (methodDeclaration.inferredType!=null)
+ methodDeclaration.inferredType.dumpReference(output);
+ else
+ output.append("??"); //$NON-NLS-1$
+ output.append(" "); //$NON-NLS-1$
+ }
+
+ output.append(name).append("("); //$NON-NLS-1$
+ if (methodDeclaration.arguments!=null)
+ for (int i = 0; i < methodDeclaration.arguments.length; i++) {
+ if (i>0)
+ output.append(", "); //$NON-NLS-1$
+ InferredType argumentType = methodDeclaration.arguments[i].inferredType;
+ if (argumentType!=null )
+ {
+ output.append(argumentType.name).append(" "); //$NON-NLS-1$
+ }
+ output.append(methodDeclaration.arguments[i].name);
+ }
+ output.append(")"); //$NON-NLS-1$
+
+ return output;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java
new file mode 100644
index 0000000..90f3eae
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferredType.java
@@ -0,0 +1,469 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IAbstractFunctionDeclaration;
+import org.eclipse.wst.jsdt.core.ast.IFunctionDeclaration;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MultipleTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TagBits;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+
+
+/**
+ * The represenation of an inferred type.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferredType extends ASTNode {
+
+ char [] name;
+ public ArrayList methods;
+ public InferredAttribute[] attributes=new InferredAttribute[5];
+ public int numberAttributes=0;
+ HashtableOfObject attributesHash = new HashtableOfObject();
+ public InferredType superClass;
+
+ public InferredType referenceClass;
+
+ public SourceTypeBinding binding;
+ public boolean isDefinition;
+ private TypeBinding resolvedType;
+ public ClassScope scope;
+ ReferenceBinding resolvedSuperType;
+
+ public boolean isArray=false;
+ public boolean isAnonymous=false;
+ public boolean isObjectLiteral=false;
+
+ private int nameStart = -1;
+
+ public String inferenceProviderID;
+ public String inferenceStyle;
+
+ public ArrayList mixins;
+
+ public final static char[] OBJECT_NAME=new char[]{'O','b','j','e','c','t'};
+ public final static char[] OBJECT_LITERAL_NAME = new char[]{'{','}'};
+
+ public final static char[] ARRAY_NAME=new char[]{'A','r','r','a','y'};
+ public final static char[] FUNCTION_NAME=new char[]{'F','u','n','c','t','i','o','n'};
+ public final static char[] GLOBAL_NAME=new char[]{'G','l','o','b','a','l'};
+
+ public Object userData;
+
+ boolean allStatic=false;
+
+ /**
+ * Create a new inferred type
+ *
+ * @param className inferred type name
+ */
+ public InferredType(char [] className)
+ {
+ this.name=className;
+ this.sourceStart=-1;
+ }
+
+ /**
+ * Gets the name of the inferred type
+ *
+ * @return the inferred type name
+ */
+ public char [] getName() {
+ return name;
+ }
+
+ /**
+ * Get the superclass name of the inferred type
+ *
+ * @return superclass name
+ */
+ public char [] getSuperClassName()
+ {
+ return superClass!=null ? superClass.getName() : OBJECT_NAME;
+ }
+
+ /**
+ * Add a new inferred attribute to the inferred type
+ *
+ * @param name the attribute name
+ * @param definer the ASTNode which this attribute is inferred from
+ * @param nameStart character position (in the source) of the attribute name
+ * @return a new InferredAttribute
+ */
+ public InferredAttribute addAttribute(char [] name, IASTNode definer, int nameStart)
+ {
+ InferredAttribute attribute = findAttribute(name);
+ if (attribute==null)
+ {
+ attribute=new InferredAttribute(name, this, definer);
+ attribute.node=(ASTNode)definer;
+
+ if (this.numberAttributes == this.attributes.length)
+
+ System.arraycopy(
+ this.attributes,
+ 0,
+ this.attributes = new InferredAttribute[this.numberAttributes * 2],
+ 0,
+ this.numberAttributes );
+ this.attributes [this.numberAttributes ++] = attribute;
+
+
+ attributesHash.put(name, attribute);
+
+ if (!isAnonymous) {
+ this.updatePositions(definer.sourceStart(), definer.sourceEnd());
+ }
+ }
+ attribute.nameStart = nameStart;
+ return attribute;
+ }
+
+ /**
+ * Add an InferredAttribute to this inferred type.
+ *
+ * @param newAttribute the attribute to add.
+ * @return
+ */
+ public InferredAttribute addAttribute(InferredAttribute newAttribute)
+ {
+ IASTNode definer=newAttribute.node;
+ InferredAttribute attribute = findAttribute(newAttribute.name);
+ if (attribute==null)
+ {
+
+ if (this.numberAttributes == this.attributes.length)
+
+ System.arraycopy(
+ this.attributes,
+ 0,
+ this.attributes = new InferredAttribute[this.numberAttributes * 2],
+ 0,
+ this.numberAttributes );
+ this.attributes [this.numberAttributes ++] = newAttribute;
+
+
+ attributesHash.put(newAttribute.name, newAttribute);
+
+ if (!isAnonymous) {
+ if (definer != null) {
+ this.updatePositions(definer.sourceStart(), definer.sourceEnd());
+ }
+ else {
+ this.updatePositions(newAttribute.sourceStart(), newAttribute.sourceEnd());
+ }
+ }
+ }
+ return newAttribute;
+ }
+ /**
+ * Find the inferred attribute with the given name
+ *
+ * @param name name of the attribute to find
+ * @return the found InferredAttribute, or null if not found
+ */
+ public InferredAttribute findAttribute(char [] name)
+ {
+ return (InferredAttribute)attributesHash.get(name);
+// if (attributes!=null)
+// for (Iterator attrIterator = attributes.iterator(); attrIterator.hasNext();) {
+// InferredAttribute attribute = (InferredAttribute) attrIterator.next();
+// if (CharOperation.equals(name,attribute.name))
+// return attribute;
+// }
+// return null;
+ }
+
+
+ /**
+ * Add a new constructor method to the inferred type
+ *
+ * @param methodName name of the method to add
+ * @param functionDeclaration the AST Node containing the method bode
+ * @param nameStart character position (in the source) of the method name
+ * @return a new inferred method
+ */
+ public InferredMethod addConstructorMethod(char [] methodName, IFunctionDeclaration functionDeclaration, int nameStart) {
+ InferredMethod method = this.addMethod(methodName, functionDeclaration, nameStart, true);
+ method.isConstructor = true;
+ this.setNameStart(nameStart);
+ method.getFunctionDeclaration().setInferredType(this);
+ return method;
+ }
+
+ /**
+ * Add a new method to the inferred type
+ *
+ * @param methodName name of the method to add
+ * @param functionDeclaration the AST Node containing the method bode
+ * @param nameStart character position (in the source) of the method name
+ * @return a new inferred method
+ */
+ public InferredMethod addMethod(char [] methodName, IFunctionDeclaration functionDeclaration, int nameStart) {
+ return this.addMethod(methodName, functionDeclaration, nameStart, false);
+ }
+
+ /**
+ * Add a new method to the inferred type
+ *
+ * @param methodName name of the method to add
+ * @param functionDeclaration the AST Node containing the method bode
+ * @param isConstructor true if it is a constructor
+ * @return a new inferred method
+ */
+ private InferredMethod addMethod(char [] methodName, IFunctionDeclaration functionDeclaration, int nameStart, boolean isConstructor) {
+ MethodDeclaration methodDeclaration = (MethodDeclaration)functionDeclaration;
+ InferredMethod method = findMethod(methodName, methodDeclaration);
+ if (method==null) {
+ method=new InferredMethod(methodName,methodDeclaration,this);
+ if (methodDeclaration.inferredMethod==null)
+ methodDeclaration.inferredMethod = method;
+ else
+ {
+ if (isConstructor)
+ {
+ methodDeclaration.inferredMethod.inType=this;
+ method.isStatic=methodDeclaration.inferredMethod.isStatic;
+ method.bits=methodDeclaration.inferredMethod.bits;
+ methodDeclaration.inferredMethod = method;
+ } else if (methodDeclaration.inferredMethod.isConstructor)
+ method.inType=methodDeclaration.inferredMethod.inType;
+
+ }
+ if (methods==null)
+ methods=new ArrayList();
+ methods.add(method);
+
+ if( !isAnonymous )
+ this.updatePositions(methodDeclaration.sourceStart, methodDeclaration.sourceEnd);
+ method.isConstructor=isConstructor;
+ method.nameStart = nameStart;
+ } else {
+ if (methodDeclaration.inferredMethod==null) {
+ methodDeclaration.inferredMethod=method;
+ }
+ }
+
+ return method;
+ }
+
+ /**
+ * Find an inferred method
+ *
+ * @param methodName name of the method to find
+ * @param methodDeclaration not used
+ * @return the found method, or null
+ */
+ public InferredMethod findMethod(char [] methodName, IFunctionDeclaration methodDeclaration) {
+ boolean isConstructor= methodName==TypeConstants.INIT;
+ if (methods!=null)
+ for (Iterator methodIterator = methods.iterator(); methodIterator.hasNext();) {
+ InferredMethod method = (InferredMethod) methodIterator.next();
+ if (CharOperation.equals(methodName,method.name))
+ return method;
+ if (isConstructor && method.isConstructor)
+ return method;
+ }
+ return null;
+
+ }
+
+ public TypeBinding resolveType(Scope scope, ASTNode node) {
+ // handle the error here
+ if (this.resolvedType != null) // is a shared type reference which was already resolved
+ return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+
+ if (isArray())
+ {
+ TypeBinding memberType = (referenceClass!=null)?referenceClass.resolveType(scope,node):null;
+ if (memberType==null)
+ memberType=TypeBinding.UNKNOWN;
+ this.resolvedType=new ArrayBinding(memberType, 1, scope.compilationUnitScope().environment) ;
+
+ }
+ else {
+ if (CharOperation.indexOf('|', name)>0)
+ {
+ char[][] names = CharOperation.splitAndTrimOn('|', name);
+ this.resolvedType=new MultipleTypeBinding(scope,names);
+ }
+ else
+ this.resolvedType = scope.getType(name);
+ /* the inferred type isn't valid, so don't assign it to the variable */
+ if(!this.resolvedType.isValidBinding()) this.resolvedType = null;
+ }
+
+
+ if (this.resolvedType == null)
+ return null; // detected cycle while resolving hierarchy
+ if (node!=null && !this.resolvedType.isValidBinding()) {
+ scope.problemReporter().invalidType(node, this.resolvedType);
+ return null;
+ }
+ if (node!=null && node.isTypeUseDeprecated(this.resolvedType, scope))
+ scope.problemReporter().deprecatedType(this.resolvedType, node);
+
+ if( isAnonymous )
+ this.resolvedType.tagBits |= TagBits.AnonymousTypeMask;
+
+ return this.resolvedType ;
+ }
+
+
+
+ public void dumpReference(StringBuffer sb)
+ {
+ sb.append(name);
+ if (referenceClass!=null)
+ {
+ sb.append('(');
+ referenceClass.dumpReference(sb);
+ sb.append(')');
+ }
+ }
+
+ public boolean containsMethod(IAbstractFunctionDeclaration inMethod) {
+ if (methods!=null)
+ for (Iterator iter = methods.iterator(); iter.hasNext();) {
+ InferredMethod method = (InferredMethod) iter.next();
+ if (method.getFunctionDeclaration()==inMethod)
+ return true;
+ }
+ return false;
+ }
+
+
+
+ public ReferenceBinding resolveSuperType(ClassScope classScope) {
+ if (this.resolvedSuperType != null)
+ return this.resolvedSuperType;
+
+ if(superClass != null)
+ this.resolvedSuperType = (ReferenceBinding)classScope.getType(superClass.getName());
+
+ return this.resolvedSuperType;
+ }
+
+ public boolean isArray()
+ {
+ return CharOperation.equals(ARRAY_NAME, name);
+ }
+
+ public boolean isFunction()
+ {
+ return CharOperation.equals(FUNCTION_NAME, name);
+ }
+
+ public StringBuffer print(int indent, StringBuffer output) {
+ printIndent(indent, output);
+ char[] superName= getSuperClassName();
+ output.append("class ").append(name).append(" extends ").append(superName).append("{\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ for (int i=0;i=0 && start0&&end>this.sourceEnd)
+ this.sourceEnd=end;
+ }
+
+ public IAbstractFunctionDeclaration declarationOf(MethodBinding methodBinding) {
+ if (methodBinding != null && this.methods != null) {
+ for (int i = 0, max = this.methods.size(); i < max; i++) {
+ InferredMethod method=(InferredMethod) this.methods.get(i);
+
+ if (method.methodBinding==methodBinding)
+ return method.getFunctionDeclaration();
+ }
+ }
+ return null;
+ }
+
+ public boolean isNamed()
+ {
+ return !isAnonymous || !CharOperation.prefixEquals(IInferEngine.ANONYMOUS_PREFIX, this.name);
+ }
+
+ /**
+ * Set the charactor position (in the source) of the type name
+ *
+ * @param start type name position
+ */
+ public void setNameStart(int start)
+ {
+ this.nameStart=start;
+ }
+
+ public int getNameStart()
+ {
+ return this.nameStart!= -1 ? this.nameStart : this.sourceStart;
+ }
+
+ public boolean isEmptyGlobal()
+ {
+ return (CharOperation.equals(GLOBAL_NAME, this.name) &&
+ this.numberAttributes==0 &&
+ (this.methods==null || this.methods.isEmpty()));
+ }
+
+
+ /**
+ * Adds the name of a type to mix into this type once all of the types have
+ * been inferred
+ *
+ * @param mixinTypeName the name of the type to mix into this type
+ */
+ public void addMixin(char[] mixinTypeName)
+ {
+ if (mixins==null)
+ mixins=new ArrayList();
+ mixins.add(mixinTypeName);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceManager.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceManager.java
new file mode 100644
index 0000000..e80fe85
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceManager.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.core.util.Util;
+
+
+/**
+ *
+ * Internal
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferrenceManager {
+
+ public static final String EXTENSION_POINT= "inferrenceSupport"; //$NON-NLS-1$
+
+ protected static final String TAG_INFERENCE_PROVIDER = "inferenceProvider"; //$NON-NLS-1$
+ protected static final String ATTR_INFERENGINE_CLASS = "class"; //$NON-NLS-1$
+
+
+ private static InferrenceManager instance = null;
+
+
+ private InferrenceSupportExtension [] extensions;
+
+ public static InferrenceManager getInstance(){
+ if( instance == null )
+ instance = new InferrenceManager();
+
+ return instance;
+ }
+
+
+
+ public InferrenceProvider [] getInferenceProviders()
+ {
+
+ if (extensions==null)
+ {
+ loadInferenceExtensions();
+ }
+ ArrayList extProviders=new ArrayList();
+ extProviders.add(new DefaultInferrenceProvider());
+ for (int i = 0; i < extensions.length; i++) {
+ if (extensions[i].inferProvider!=null)
+ extProviders.add(extensions[i].inferProvider);
+ }
+ return (InferrenceProvider [] )extProviders.toArray(new InferrenceProvider[extProviders.size()]);
+ }
+
+
+ public InferrenceProvider [] getInferenceProviders(IInferenceFile script)
+ {
+ InferrenceProvider[] inferenceProviders = getInferenceProviders();
+ List extProviders=new ArrayList(inferenceProviders.length);
+ for (int i = 0; i < inferenceProviders.length; i++) {
+ int applies = inferenceProviders[i].applysTo(script);
+ switch (applies) {
+ case InferrenceProvider.MAYBE_THIS:
+ extProviders.add(inferenceProviders[i]);
+ break;
+
+ case InferrenceProvider.ONLY_THIS:
+ InferrenceProvider [] thisProvider = {inferenceProviders[i]};
+ return thisProvider;
+
+
+ default:
+ break;
+ }
+ }
+ return (InferrenceProvider [] )extProviders.toArray(new InferrenceProvider[extProviders.size()]);
+ }
+
+
+
+
+ public IInferEngine [] getInferenceEngines(CompilationUnitDeclaration script)
+ {
+ InferrenceProvider[] inferenceProviders = getInferenceProviders();
+ if (inferenceProviders.length==1)
+ return getSingleEngine(inferenceProviders[0]);
+
+ List extEngines=new ArrayList();
+ for (int i = 0; i < inferenceProviders.length; i++) {
+ if (script.compilationResult!=null && script.compilationResult.compilationUnit!=null)
+ {
+ String inferenceID = script.compilationResult.compilationUnit.getInferenceID();
+ if (inferenceProviders[i].getID().equals(inferenceID)) {
+ return getSingleEngine(inferenceProviders[i]);
+// InferEngine eng=inferenceProviders[i].getInferEngine();
+// eng.appliesTo=InferrenceProvider.MAYBE_THIS;
+// eng.inferenceProvider=inferenceProviders[i];
+// extEngines.add(eng);
+// continue;
+ }
+ }
+ int applies = InferrenceProvider.NOT_THIS;
+ try {
+ applies = inferenceProviders[i].applysTo(script);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ Util.log(e, "exception in inference provider "+inferenceProviders[i].getID());
+ }
+ switch (applies) {
+ case InferrenceProvider.MAYBE_THIS:
+ IInferEngine eng=inferenceProviders[i].getInferEngine();
+ extEngines.add(eng);
+ break;
+
+ case InferrenceProvider.ONLY_THIS:
+ return getSingleEngine(inferenceProviders[i]);
+
+
+ default:
+ break;
+ }
+ }
+ return (IInferEngine [] )extEngines.toArray(new IInferEngine[extEngines.size()]);
+ }
+
+
+ private IInferEngine [] getSingleEngine(InferrenceProvider provider)
+ {
+ IInferEngine engine=provider.getInferEngine();
+ IInferEngine [] thisEngine = {engine};
+ return thisEngine;
+ }
+
+
+ protected void loadInferenceExtensions() {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ ArrayList extList = new ArrayList();
+ if (registry != null) {
+ IExtensionPoint point = registry.getExtensionPoint(
+ JavaScriptCore.PLUGIN_ID, EXTENSION_POINT);
+
+ if (point != null) {
+ IExtension[] extensions = point.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] elements = extensions[i]
+ .getConfigurationElements();
+ for (int j = 0; j < elements.length; j++) {
+ try {
+ InferrenceProvider inferProvider = null;
+ if (elements[j].getName().equals(TAG_INFERENCE_PROVIDER)) {
+ inferProvider = (InferrenceProvider) elements[j]
+ .createExecutableExtension(ATTR_INFERENGINE_CLASS);
+ }
+ InferrenceSupportExtension inferenceSupport = new InferrenceSupportExtension();
+ inferenceSupport.inferProvider = inferProvider;
+
+ extList.add(inferenceSupport);
+ } catch (CoreException e) {
+ Util.log(e, "Error in loading inference extension");
+ }
+ }
+ }
+ }
+ }
+
+ this.extensions = (InferrenceSupportExtension[]) extList
+ .toArray(new InferrenceSupportExtension[extList.size()]);
+ }
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceProvider.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceProvider.java
new file mode 100644
index 0000000..d5dfc70
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceProvider.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+
+/**
+ * Implemented by contributors to the
+ * org.eclipse.wst.jsdt.core.infer.inferrenceSupport extension point
+ *
+ * Provisional API: This class/interface is part of an interim API that is
+ * still under development and expected to change significantly before
+ * reaching stability. It is being made available at this early stage to
+ * solicit feedback from pioneering adopters on the understanding that any
+ * code that uses this API will almost certainly be broken (repeatedly) as the
+ * API evolves.
+ */
+public interface InferrenceProvider {
+
+ /**
+ *
+ * Indicates that this InferrenceProvider, and its engine, are the
+ * only ones that should apply to a script file.
+ *
+ *
+ * Its use is discouraged.
+ *
+ */
+ public static final int ONLY_THIS = 1;
+
+ /**
+ *
+ * Indicates that this InferrenceProvider, and its engine, do not apply to
+ * a script file.
+ *
+ */
+ public static final int NOT_THIS = 2;
+
+ /**
+ *
+ * Indicates that this InferrenceProvider, and its engine, should
+ * also apply to a script file. As multiple providers may
+ * be required and used to completely understand a script file, this value
+ * is suggested as a default. Care should then be taken to avoid
+ * duplicating the contributions of the default provider.
+ *
+ */
+ public static final int MAYBE_THIS = 3;
+
+ /**
+ * Get the inference engine for this inference provider, or null if one
+ * will not be provided. Implementors returning null are expected to have
+ * returned {@link #NOT_THIS} from all calls to {@link #getInferEngine()}
+ *
+ * @return an inference engine
+ */
+ public IInferEngine getInferEngine();
+
+
+ /**
+ * Determine if this inference provider applies to a script
+ *
+ * @param scriptFile
+ * the script on which the inferencing will be done
+ * @return {@link #ONLY_THIS}, {@link #NOT_THIS}, {@link #MAYBE_THIS}
+ * depending on how much this inference provider applies to the
+ * specified script. See the documentation for each constant for
+ * when each should be used.
+ */
+ public int applysTo(IInferenceFile scriptFile);
+
+
+ /**
+ * Get the inference provider ID
+ *
+ * @return the id of this inference provider
+ */
+ public String getID();
+
+
+ /**
+ * @return the ResolutionConfiguration used to resolve the inferred
+ * classes
+ */
+ public ResolutionConfiguration getResolutionConfiguration();
+
+ /**
+ * @return the RefactoringSupport used to provide refactoring for inferred
+ * types, or null if it is not offered.
+ */
+ public RefactoringSupport getRefactoringSupport();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceSupportExtension.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceSupportExtension.java
new file mode 100644
index 0000000..faafd95
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/InferrenceSupportExtension.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+
+/**
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class InferrenceSupportExtension {
+ public InferrenceProvider inferProvider;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/RefactoringSupport.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/RefactoringSupport.java
new file mode 100644
index 0000000..f29ea06
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/RefactoringSupport.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+
+/**
+ * Support for refactoring of inferred types
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+
+public class RefactoringSupport {
+
+ /**
+ * @return a ImportRewriteSupport instance if it is desired to participate in import writing
+ *
+ * @see ImportRewriteSupport
+ */
+ public ImportRewriteSupport getImportRewriteSupport()
+ {
+ return null;
+ }
+
+ /**
+ * Determines if the inferred classes can safely be renamed.
+ *
+ * @return true if the inferred class can safely be renamed
+ *
+ */
+
+ public boolean supportsClassRename()
+ {
+ return false;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/ResolutionConfiguration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/ResolutionConfiguration.java
new file mode 100644
index 0000000..bc48f68
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/infer/ResolutionConfiguration.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.infer;
+
+/**
+ * This class provides configuration information for when the inferred class
+ * gets resolved
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class ResolutionConfiguration {
+
+
+ /**
+ * Get the default list of files to be looked at when resolving
+ * a name
+ * @return a list of file paths as strings, relative to the JavaScript project root
+ */
+ public String [] getContextIncludes()
+ {
+ return null;
+ }
+
+ /**
+ * Determine if all files in include path should be searched to resolve a name.
+ * If false, names will be resolved using only libraries, imports, and context includes
+ *
+ * @return true
+ */
+ public boolean searchAllFiles()
+ {
+ return true;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/messages.properties b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/messages.properties
new file mode 100644
index 0000000..0339eff
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/messages.properties
@@ -0,0 +1 @@
+LibrarySuperType.0={0}() in {1}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/FieldDeclarationMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/FieldDeclarationMatch.java
new file mode 100644
index 0000000..12ecf7a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/FieldDeclarationMatch.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a field declaration.
+ * The element is an IField
.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FieldDeclarationMatch extends SearchMatch {
+
+ /**
+ * Creates a new field declaration match.
+ *
+ * @param element the field declaration
+ * @param accuracy one of A_ACCURATE or A_INACCURATE
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public FieldDeclarationMatch(IJavaScriptElement element, int accuracy, int offset, int length, SearchParticipant participant, IResource resource) {
+ super(element, accuracy, offset, length, participant, resource);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/FieldReferenceMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/FieldReferenceMatch.java
new file mode 100644
index 0000000..4e174d3
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/FieldReferenceMatch.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a field reference.
+ * The element is the inner-most enclosing member that references this field.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class FieldReferenceMatch extends SearchMatch {
+
+ private boolean isReadAccess;
+ private boolean isWriteAccess;
+
+ /**
+ * Creates a new field reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this field
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param isReadAccess whether the match represents a read access
+ * @param isWriteAccess whether the match represents a write access
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public FieldReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean isReadAccess, boolean isWriteAccess, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ super(enclosingElement, accuracy, offset, length, participant, resource);
+ this.isReadAccess = isReadAccess;
+ this.isWriteAccess = isWriteAccess;
+ setInsideDocComment(insideDocComment);
+ }
+
+ /**
+ * Returns whether the field reference is a read access to the field.
+ * Note that a field reference can be read and written at once in case of compound assignments (e.g. i += 0;)
+ *
+ * @return whether the field reference is a read access to the field.
+ */
+ public final boolean isReadAccess() {
+ return this.isReadAccess;
+ }
+
+ /**
+ * Returns whether the field reference is a write access to the field.
+ * Note that a field reference can be read and written at once in case of compound assignments (e.g. i += 0;)
+ *
+ * @return whether the field reference is a write access to the field.
+ */
+ public final boolean isWriteAccess() {
+ return this.isWriteAccess;
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/IJavaScriptSearchConstants.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/IJavaScriptSearchConstants.java
new file mode 100644
index 0000000..baf9040
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/IJavaScriptSearchConstants.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.wst.jsdt.internal.core.search.processing.IJob;
+
+/**
+ *
+ * This interface defines the constants used by the search engine.
+ *
+ *
+ * This interface declares constants only; it is not intended to be implemented.
+ *
+ * @see org.eclipse.wst.jsdt.core.search.SearchEngine
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IJavaScriptSearchConstants {
+
+ /**
+ * The nature of searched element or the nature
+ * of match in unknown.
+ */
+ int UNKNOWN = -1;
+
+ /* Nature of searched element */
+
+ /**
+ * The searched element is a type, which may include classes, interfaces,
+ * enums, and annotation types.
+ */
+ int TYPE= 0;
+
+ /**
+ * The searched element is a method.
+ */
+ int METHOD= 1;
+
+ /**
+ * The searched element is a package.
+ */
+ int PACKAGE= 2;
+
+ /**
+ * The searched element is a constructor.
+ */
+ int CONSTRUCTOR= 3;
+
+ /**
+ * The searched element is a field.
+ */
+ int FIELD= 4;
+
+ /**
+ * The searched element is a class.
+ * More selective than using {@link #TYPE}.
+ */
+ int CLASS= 5;
+
+ /**
+ * The searched element is an enum.
+ * More selective than using {@link #TYPE}.
+ *
+ */
+ int ENUM= 7;
+
+ /**
+ * The searched element is a field.
+ */
+ int VAR= 12;
+ int FUNCTION= 13;
+
+ /* Nature of match */
+
+ /**
+ * The search result is a declaration.
+ * Can be used in conjunction with any of the nature of searched elements
+ * so as to better narrow down the search.
+ */
+ int DECLARATIONS= 0;
+
+ /**
+ * The search result is a type that extends a class.
+ * Used in conjunction with either TYPE or CLASS, it will
+ * respectively search for any type extending a type,
+ * or rather exclusively search for classes extending the type.
+ */
+ int IMPLEMENTORS= 1;
+
+ /**
+ * The search result is a reference.
+ * Can be used in conjunction with any of the nature of searched elements
+ * so as to better narrow down the search.
+ * References can contain implementers since they are more generic kind
+ * of matches.
+ */
+ int REFERENCES= 2;
+
+ /**
+ * The search result is a declaration, a reference, or an implementer
+ * of an interface.
+ * Can be used in conjunction with any of the nature of searched elements
+ * so as to better narrow down the search.
+ */
+ int ALL_OCCURRENCES= 3;
+
+ /**
+ * When searching for field matches, it will exclusively find read accesses, as
+ * opposed to write accesses. Note that some expressions are considered both
+ * as field read/write accesses: for example, x++; x+= 1;
+ *
+ *
+ */
+ int READ_ACCESSES = 4;
+
+ /**
+ * When searching for field matches, it will exclusively find write accesses, as
+ * opposed to read accesses. Note that some expressions are considered both
+ * as field read/write accesses: for example, x++; x+= 1;
+ *
+ *
+ */
+ int WRITE_ACCESSES = 5;
+
+ /**
+ * Ignore declaring type while searching result.
+ * Can be used in conjunction with any of the nature of match.
+ *
+ */
+ int IGNORE_DECLARING_TYPE = 0x10;
+
+ /**
+ * Ignore return type while searching result.
+ * Can be used in conjunction with any of the nature of match.
+ * Note that:
+ *
+ * - for fields search, pattern will ignore field type
+ * - this flag will have no effect for types search
+ *
+ *
+ */
+ int IGNORE_RETURN_TYPE = 0x20;
+
+ /* Syntactic match modes */
+
+ /**
+ * The search operation starts immediately, even if the underlying indexer
+ * has not finished indexing the workspace. Results will more likely
+ * not contain all the matches.
+ */
+ int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate;
+ /**
+ * The search operation throws an org.eclipse.core.runtime.OperationCanceledException
+ * if the underlying indexer has not finished indexing the workspace.
+ */
+ int CANCEL_IF_NOT_READY_TO_SEARCH = IJob.CancelIfNotReady;
+ /**
+ * The search operation waits for the underlying indexer to finish indexing
+ * the workspace before starting the search.
+ */
+ int WAIT_UNTIL_READY_TO_SEARCH = IJob.WaitUntilReady;
+
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/IJavaScriptSearchScope.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/IJavaScriptSearchScope.java
new file mode 100644
index 0000000..f8fcd39
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/IJavaScriptSearchScope.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * An IJavaScriptSearchScope
defines where search result should be found by a
+ * SearchEngine
. Clients must pass an instance of this interface
+ * to the search(...)
methods. Such an instance can be created using the
+ * following factory methods on SearchEngine
: createHierarchyScope(IType)
,
+ * createJavaSearchScope(IResource[])
, createWorkspaceScope()
, or
+ * clients may choose to implement this interface.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IJavaScriptSearchScope {
+/**
+ * This constant defines the separator of the resourcePath string of the encloses(String)
+ * method. If present in the string, it separates the path to the jar file from the path
+ * to the .class file in the jar.
+ */
+String JAR_FILE_ENTRY_SEPARATOR = "|"; //$NON-NLS-1$
+/**
+ * Include type constant (bit mask) indicating that source folders should be considered in the search scope.
+ *
+ */
+int SOURCES = 1;
+/**
+ * Include type constant (bit mask) indicating that application libraries should be considered in the search scope.
+ *
+ */
+int APPLICATION_LIBRARIES = 2;
+/**
+ * Include type constant (bit mask) indicating that system libraries should be considered in the search scope.
+ *
+ */
+int SYSTEM_LIBRARIES = 4;
+/**
+ * Include type constant (bit mask) indicating that referenced projects should be considered in the search scope.
+ *
+ */
+int REFERENCED_PROJECTS = 8;
+/**
+ * Checks whether the resource at the given path is enclosed by this scope.
+ *
+ * @param resourcePath if the resource is contained in
+ * a JAR file, the path is composed of 2 paths separated
+ * by JAR_FILE_ENTRY_SEPARATOR
: the first path is the full OS path
+ * to the JAR (if it is an external JAR), or the workspace relative IPath
+ * to the JAR (if it is an internal JAR),
+ * the second path is the path to the resource inside the JAR.
+ * @return whether the resource is enclosed by this scope
+ */
+public boolean encloses(String resourcePath);
+/**
+ * Checks whether this scope encloses the given element.
+ *
+ * @param element the given element
+ * @return true
if the element is in this scope
+ */
+public boolean encloses(IJavaScriptElement element);
+/**
+ * Returns the paths to the enclosing projects and JARs for this search scope.
+ *
+ * - If the path is a project path, this is the full path of the project
+ * (see
IResource.getFullPath()
).
+ * For example, /MyProject
+ *
+ * - If the path is a JAR path and this JAR is internal to the workspace,
+ * this is the full path of the JAR file (see
IResource.getFullPath()
).
+ * For example, /MyProject/mylib.jar
+ *
+ * - If the path is a JAR path and this JAR is external to the workspace,
+ * this is the full OS path to the JAR file on the file system.
+ * For example, d:\libs\mylib.jar
+ *
+ *
+ *
+ * @return an array of paths to the enclosing projects and JARS.
+ */
+IPath[] enclosingProjectsAndJars();
+public boolean shouldExclude(String container, String resourceName);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/LocalVariableDeclarationMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/LocalVariableDeclarationMatch.java
new file mode 100644
index 0000000..02a2c8a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/LocalVariableDeclarationMatch.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a local variable declaration.
+ * The element is an ILocalVariable
.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class LocalVariableDeclarationMatch extends SearchMatch {
+
+ /**
+ * Creates a new local variable declaration match.
+ *
+ * @param element the local variable declaration
+ * @param accuracy one of A_ACCURATE or A_INACCURATE
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public LocalVariableDeclarationMatch(IJavaScriptElement element, int accuracy, int offset, int length, SearchParticipant participant, IResource resource) {
+ super(element, accuracy, offset, length, participant, resource);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/LocalVariableReferenceMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/LocalVariableReferenceMatch.java
new file mode 100644
index 0000000..223348b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/LocalVariableReferenceMatch.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a local variable reference.
+ * The element is the inner-most enclosing member that references this local variable.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class LocalVariableReferenceMatch extends SearchMatch {
+
+ private boolean isReadAccess;
+ private boolean isWriteAccess;
+
+ /**
+ * Creates a new local variable reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this local variable
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param isReadAccess whether the match represents a read access
+ * @param isWriteAccess whethre the match represents a write access
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public LocalVariableReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean isReadAccess, boolean isWriteAccess, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ super(enclosingElement, accuracy, offset, length, participant, resource);
+ this.isReadAccess = isReadAccess;
+ this.isWriteAccess = isWriteAccess;
+ setInsideDocComment(insideDocComment);
+ }
+
+ /**
+ * Returns whether the local variable reference is a read access to the variable.
+ * Note that a local variable reference can be read and written at once in case of compound assignments (e.g. i += 0;)
+ *
+ * @return whether the local variable reference is a read access to the variable.
+ */
+ public final boolean isReadAccess() {
+ return this.isReadAccess;
+ }
+
+ /**
+ * Returns whether the local variable reference is a write access to the variable.
+ * Note that a local variable reference can be read and written at once in case of compound assignments (e.g. i += 0;)
+ *
+ * @return whether the local variable reference is a write access to the variable.
+ */
+ public final boolean isWriteAccess() {
+ return this.isWriteAccess;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/MethodDeclarationMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/MethodDeclarationMatch.java
new file mode 100644
index 0000000..109e00a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/MethodDeclarationMatch.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a method declaration.
+ * The element is an IFunction
.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class MethodDeclarationMatch extends SearchMatch {
+
+ /**
+ * Creates a new method declaration match.
+ *
+ * @param element the method declaration
+ * @param accuracy one of A_ACCURATE or A_INACCURATE
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public MethodDeclarationMatch(IJavaScriptElement element, int accuracy, int offset, int length, SearchParticipant participant, IResource resource) {
+ super(element, accuracy, offset, length, participant, resource);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/MethodReferenceMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/MethodReferenceMatch.java
new file mode 100644
index 0000000..bbce4db
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/MethodReferenceMatch.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a method reference.
+ * The element is the inner-most enclosing member that references this method.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class MethodReferenceMatch extends SearchMatch {
+ private boolean constructor;
+ private boolean superInvocation;
+
+ /**
+ * Creates a new method reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this method
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public MethodReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ super(enclosingElement, accuracy, offset, length, participant, resource);
+ setInsideDocComment(insideDocComment);
+ }
+
+ /**
+ * Creates a new method reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this method
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param constructor true
if this search match a constructor
+ * false
otherwise
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ *
+ */
+ public MethodReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean constructor, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ this(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
+ this.constructor = constructor;
+ }
+
+ /**
+ * Creates a new method reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this method
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param constructor true
if this search matches a constructor
+ * false
otherwise
+ * @param superInvocation true
if this search matches a super-type invocation
+ * element false
otherwise
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ *
+ */
+ public MethodReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean constructor, boolean superInvocation, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ this(enclosingElement, accuracy, offset, length, constructor, insideDocComment, participant, resource);
+ this.superInvocation = superInvocation;
+ }
+
+ /**
+ * Returns whether the reference is on a constructor.
+ *
+ * @return Returns whether the reference is on a constructor or not.
+ *
+ */
+ public final boolean isConstructor() {
+ return this.constructor;
+ }
+
+ /**
+ * Returns whether the reference is on a message sent from a type
+ * which is a super type of the searched method declaring type.
+ * If true
, the method called at run-time may or may not be
+ * the search target, depending on the run-time type of the receiver object.
+ *
+ * @return true
if the reference is on a message sent from
+ * a super-type of the searched method declaring class, false
otherwise
+ */
+ public boolean isSuperInvocation() {
+ return this.superInvocation;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/PackageReferenceMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/PackageReferenceMatch.java
new file mode 100644
index 0000000..959cc6b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/PackageReferenceMatch.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a package reference.
+ * The element is the inner-most enclosing member that references this package.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class PackageReferenceMatch extends SearchMatch {
+
+ /**
+ * Creates a new package reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this package
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public PackageReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ super(enclosingElement, accuracy, offset, length, participant, resource);
+ setInsideDocComment(insideDocComment);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchDocument.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchDocument.java
new file mode 100644
index 0000000..cf03707
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchDocument.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.internal.core.search.indexing.InternalSearchDocument;
+
+/**
+ * A search document encapsulates a content to be either indexed or searched in.
+ * A search particpant creates a search document.
+ *
+ * This class is intended to be subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class SearchDocument extends InternalSearchDocument {
+ private String documentPath;
+ private SearchParticipant participant;
+
+ /**
+ * Creates a new search document. The given document path is a string that uniquely identifies the document.
+ * Most of the time it is a workspace-relative path, but it can also be a file system path, or a path inside a zip file.
+ *
+ * @param documentPath the path to the document,
+ * or null
if none
+ * @param participant the participant that creates the search document
+ */
+ protected SearchDocument(String documentPath, SearchParticipant participant) {
+ this.documentPath = documentPath;
+ this.participant = participant;
+ }
+
+ /**
+ * Adds the given index entry (category and key) coming from this
+ * document to the index. This method must be called from
+ * {@link SearchParticipant#indexDocument(SearchDocument document, org.eclipse.core.runtime.IPath indexPath)}.
+ *
+ * @param category the category of the index entry
+ * @param key the key of the index entry
+ */
+ public void addIndexEntry(char[] category, char[] key) {
+ super.addIndexEntry(category, key);
+ }
+
+ /**
+ * Returns the contents of this document.
+ * Contents may be different from actual resource at corresponding document path,
+ * in case of preprocessing.
+ *
+ * This method must be implemented in subclasses.
+ *
+ * Note: some implementation may choose to cache the contents directly on the
+ * document for performance reason. However, this could induce scalability issues due
+ * to the fact that collections of documents are manipulated throughout the search
+ * operation, and cached contents would then consume lots of memory until they are
+ * all released at once in the end.
+ *
+ *
+ * @return the contents of this document,
+ * or null
if none
+ */
+ public abstract byte[] getByteContents();
+
+ /**
+ * Returns the contents of this document.
+ * Contents may be different from actual resource at corresponding document
+ * path due to preprocessing.
+ *
+ * This method must be implemented in subclasses.
+ *
+ * Note: some implementation may choose to cache the contents directly on the
+ * document for performance reason. However, this could induce scalability issues due
+ * to the fact that collections of documents are manipulated throughout the search
+ * operation, and cached contents would then consume lots of memory until they are
+ * all released at once in the end.
+ *
+ *
+ * @return the contents of this document,
+ * or null
if none
+ */
+ public abstract char[] getCharContents();
+
+ /**
+ * Returns the encoding for this document.
+ *
+ * This method must be implemented in subclasses.
+ *
+ *
+ * @return the encoding for this document,
+ * or null
if none
+ */
+ public abstract String getEncoding();
+
+ /**
+ * Returns the participant that created this document.
+ *
+ * @return the participant that created this document
+ */
+ public final SearchParticipant getParticipant() {
+ return this.participant;
+ }
+
+ /**
+ * Returns the path to the original document to publicly mention in index
+ * or search results. This path is a string that uniquely identifies the document.
+ * Most of the time it is a workspace-relative path, but it can also be a file system path,
+ * or a path inside a zip file.
+ *
+ * @return the path to the document
+ */
+ public final String getPath() {
+ return this.documentPath;
+ }
+ /**
+ * Removes all index entries from the index for the given document.
+ * This method must be called from
+ * {@link SearchParticipant#indexDocument(SearchDocument document, org.eclipse.core.runtime.IPath indexPath)}.
+ */
+ public void removeAllIndexEntries() {
+ super.removeAllIndexEntries();
+ }
+
+ public boolean isVirtual() {
+ return false;
+
+ }
+ public IJavaScriptElement getJavaElement() {
+ return null;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchEngine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchEngine.java
new file mode 100644
index 0000000..220ffbb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchEngine.java
@@ -0,0 +1,631 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.WorkingCopyOwner;
+import org.eclipse.wst.jsdt.internal.core.search.BasicSearchEngine;
+import org.eclipse.wst.jsdt.internal.core.search.TypeNameMatchRequestorWrapper;
+import org.eclipse.wst.jsdt.internal.core.search.TypeNameRequestorWrapper;
+
+/**
+ * A {@link SearchEngine} searches for JavaScript elements following a search pattern.
+ * The search can be limited to a search scope.
+ *
+ * Various search patterns can be created using the factory methods
+ * {@link SearchPattern#createPattern(String, int, int, int)}, {@link SearchPattern#createPattern(IJavaScriptElement, int)},
+ * {@link SearchPattern#createOrPattern(SearchPattern, SearchPattern)}.
+ *
+ * For example, one can search for references to a method in the hierarchy of a type,
+ * or one can search for the declarations of types starting with "Abstract" in a project.
+ *
+ *
+ * This class may be instantiated; it is not intended to be subclassed.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SearchEngine {
+
+ // Search engine now uses basic engine functionalities
+ private BasicSearchEngine basicEngine;
+
+ /**
+ * Creates a new search engine.
+ */
+ public SearchEngine() {
+ this.basicEngine = new BasicSearchEngine();
+ }
+
+ /**
+ * Creates a new search engine with a list of working copies that will take precedence over
+ * their original javascript unit s in the subsequent search operations.
+ *
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * Since 3.0 the given working copies take precedence over primary working copies (if any).
+ *
+ * @param workingCopies the working copies that take precedence over their original javascript unit s
+ *
+ */
+ public SearchEngine(IJavaScriptUnit[] workingCopies) {
+ this.basicEngine = new BasicSearchEngine(workingCopies);
+ }
+ /**
+ * Creates a new search engine with the given working copy owner.
+ * The working copies owned by this owner will take precedence over
+ * the primary javascript unit s in the subsequent search operations.
+ *
+ * @param workingCopyOwner the owner of the working copies that take precedence over their original javascript unit s
+ *
+ */
+ public SearchEngine(WorkingCopyOwner workingCopyOwner) {
+ this.basicEngine = new BasicSearchEngine(workingCopyOwner);
+ }
+
+ /**
+ * Returns a JavaScript search scope limited to the hierarchy of the given type.
+ * The JavaScript elements resulting from a search with this scope will
+ * be types in this hierarchy, or members of the types in this hierarchy.
+ *
+ * @param type the focus of the hierarchy scope
+ * @return a new hierarchy scope
+ * @exception JavaScriptModelException if the hierarchy could not be computed on the given type
+ */
+ public static IJavaScriptSearchScope createHierarchyScope(IType type) throws JavaScriptModelException {
+ return BasicSearchEngine.createHierarchyScope(type);
+ }
+
+ /**
+ * Returns a JavaScript search scope limited to the hierarchy of the given type.
+ * When the hierarchy is computed, the types defined in the working copies owned
+ * by the given owner take precedence over the original javascript unit s.
+ * The JavaScript elements resulting from a search with this scope will
+ * be types in this hierarchy, or members of the types in this hierarchy.
+ *
+ * @param type the focus of the hierarchy scope
+ * @param owner the owner of working copies that take precedence over original javascript unit s
+ * @return a new hierarchy scope
+ * @exception JavaScriptModelException if the hierarchy could not be computed on the given type
+ *
+ */
+ public static IJavaScriptSearchScope createHierarchyScope(IType type, WorkingCopyOwner owner) throws JavaScriptModelException {
+ return BasicSearchEngine.createHierarchyScope(type, owner);
+ }
+
+ /**
+ * Returns a JavaScript search scope limited to the given JavaScript elements.
+ * The JavaScript elements resulting from a search with this scope will
+ * be children of the given elements.
+ *
+ * If an element is an IJavaScriptProject, then the project's source folders,
+ * its jars (external and internal) and its referenced projects (with their source
+ * folders and jars, recursively) will be included.
+ * If an element is an IPackageFragmentRoot, then only the package fragments of
+ * this package fragment root will be included.
+ * If an element is an IPackageFragment, then only the javascript unit and class
+ * files of this package fragment will be included. Subpackages will NOT be
+ * included.
+ *
+ * In other words, this is equivalent to using SearchEngine.createJavaSearchScope(elements, true).
+ *
+ * @param elements the JavaScript elements the scope is limited to
+ * @return a new JavaScript search scope
+ *
+ */
+ public static IJavaScriptSearchScope createJavaSearchScope(IJavaScriptElement[] elements) {
+ return BasicSearchEngine.createJavaSearchScope(elements);
+ }
+
+ /**
+ * Returns a JavaScript search scope limited to the given JavaScript elements.
+ * The JavaScript elements resulting from a search with this scope will
+ * be children of the given elements.
+ *
+ * If an element is an IJavaScriptProject, then the project's source folders,
+ * its jars (external and internal) and - if specified - its referenced projects
+ * (with their source folders and jars, recursively) will be included.
+ * If an element is an IPackageFragmentRoot, then only the package fragments of
+ * this package fragment root will be included.
+ * If an element is an IPackageFragment, then only the javascript unit and class
+ * files of this package fragment will be included. Subpackages will NOT be
+ * included.
+ *
+ * @param elements the JavaScript elements the scope is limited to
+ * @param includeReferencedProjects a flag indicating if referenced projects must be
+ * recursively included
+ * @return a new JavaScript search scope
+ *
+ */
+ public static IJavaScriptSearchScope createJavaSearchScope(IJavaScriptElement[] elements, boolean includeReferencedProjects) {
+ return BasicSearchEngine.createJavaSearchScope(elements, includeReferencedProjects);
+ }
+
+ /**
+ * Returns a JavaScript search scope limited to the given JavaScript elements.
+ * The JavaScript elements resulting from a search with this scope will
+ * be children of the given elements.
+ *
+ * If an element is an IJavaScriptProject, then it includes:
+ * - its source folders if IJavaScriptSearchScope.SOURCES is specified,
+ * - its application libraries (internal and external jars, class folders that are on the raw includepath,
+ * or the ones that are coming from a includepath path variable,
+ * or the ones that are coming from a includepath container with the K_APPLICATION kind)
+ * if IJavaScriptSearchScope.APPLICATION_LIBRARIES is specified
+ * - its system libraries (internal and external jars, class folders that are coming from an
+ * IJsGlobalScopeContainer with the K_SYSTEM kind)
+ * if IJavaScriptSearchScope.APPLICATION_LIBRARIES is specified
+ * - its referenced projects (with their source folders and jars, recursively)
+ * if IJavaScriptSearchScope.REFERENCED_PROJECTS is specified.
+ * If an element is an IPackageFragmentRoot, then only the package fragments of
+ * this package fragment root will be included.
+ * If an element is an IPackageFragment, then only the javascript unit and class
+ * files of this package fragment will be included. Subpackages will NOT be
+ * included.
+ *
+ * @param elements the JavaScript elements the scope is limited to
+ * @param includeMask the bit-wise OR of all include types of interest
+ * @return a new JavaScript search scope
+ * @see IJavaScriptSearchScope#SOURCES
+ * @see IJavaScriptSearchScope#APPLICATION_LIBRARIES
+ * @see IJavaScriptSearchScope#SYSTEM_LIBRARIES
+ * @see IJavaScriptSearchScope#REFERENCED_PROJECTS
+ *
+ */
+ public static IJavaScriptSearchScope createJavaSearchScope(IJavaScriptElement[] elements, int includeMask) {
+ return BasicSearchEngine.createJavaSearchScope(elements, includeMask);
+ }
+
+ /**
+ * Create a type name match on a given type with specific modifiers.
+ *
+ * @param type The javascript model handle of the type
+ * @param modifiers Modifiers of the type
+ * @return A non-null match on the given type.
+ *
+ */
+ public static TypeNameMatch createTypeNameMatch(IType type, int modifiers) {
+ return BasicSearchEngine.createTypeNameMatch(type, modifiers);
+ }
+
+ /**
+ * Returns a JavaScript search scope with the workspace as the only limit.
+ *
+ * @return a new workspace scope
+ */
+ public static IJavaScriptSearchScope createWorkspaceScope() {
+ return BasicSearchEngine.createWorkspaceScope();
+ }
+ /**
+ * Returns a new default JavaScript search participant.
+ *
+ * @return a new default JavaScript search participant
+ *
+ */
+ public static SearchParticipant getDefaultSearchParticipant() {
+ return BasicSearchEngine.getDefaultSearchParticipant();
+ }
+
+ /**
+ * Searches for matches of a given search pattern. Search patterns can be created using helper
+ * methods (from a String pattern or a JavaScript element) and encapsulate the description of what is
+ * being searched (for example, search method declarations in a case sensitive way).
+ *
+ * @param pattern the pattern to search
+ * @param participants the particpants in the search
+ * @param scope the search scope
+ * @param requestor the requestor to report the matches to
+ * @param monitor the progress monitor used to report progress
+ * @exception CoreException if the search failed. Reasons include:
+ *
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void search(SearchPattern pattern, SearchParticipant[] participants, IJavaScriptSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+ this.basicEngine.search(pattern, participants, scope, requestor, monitor);
+ }
+
+ /**
+ * Searches for all top-level types and member types in the given scope.
+ * The search can be selecting specific types (given a package name using specific match mode
+ * and/or a type name using another specific match mode).
+ *
+ * @param packageName the full name of the package of the searched types, or a prefix for this
+ * package, or a wild-carded string for this package.
+ * May be null
, then any package name is accepted.
+ * @param typeName the dot-separated qualified name of the searched type (the qualification include
+ * the enclosing types if the searched type is a member type), or a prefix
+ * for this type, or a wild-carded string for this type.
+ * May be null
, then any type name is accepted.
+ * @param packageMatchRule one of
+ *
+ * - {@link SearchPattern#R_EXACT_MATCH} if the package name and type name are the full names
+ * of the searched types.
+ * - {@link SearchPattern#R_PREFIX_MATCH} if the package name and type name are prefixes of the names
+ * of the searched types.
+ * - {@link SearchPattern#R_PATTERN_MATCH} if the package name and type name contain wild-cards.
+ * - {@link SearchPattern#R_CAMELCASE_MATCH} if type name are camel case of the names of the searched types.
+ *
+ * combined with {@link SearchPattern#R_CASE_SENSITIVE},
+ * e.g. {@link SearchPattern#R_EXACT_MATCH} | {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * or {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case sensitive match is requested.
+ * @param typeMatchRule one of
+ *
+ * - {@link SearchPattern#R_EXACT_MATCH} if the package name and type name are the full names
+ * of the searched types.
+ * - {@link SearchPattern#R_PREFIX_MATCH} if the package name and type name are prefixes of the names
+ * of the searched types.
+ * - {@link SearchPattern#R_PATTERN_MATCH} if the package name and type name contain wild-cards.
+ * - {@link SearchPattern#R_CAMELCASE_MATCH} if type name are camel case of the names of the searched types.
+ *
+ * combined with {@link SearchPattern#R_CASE_SENSITIVE},
+ * e.g. {@link SearchPattern#R_EXACT_MATCH} | {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * or {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case sensitive match is requested.
+ * @param searchFor determines the nature of the searched elements
+ *
+ * - {@link IJavaScriptSearchConstants#CLASS}: only look for classes
+ * - {@link IJavaScriptSearchConstants#INTERFACE}: only look for interfaces
+ * - {@link IJavaScriptSearchConstants#ENUM}: only look for enumeration
+ * - {@link IJavaScriptSearchConstants#ANNOTATION_TYPE}: only look for annotation type
+ * - {@link IJavaScriptSearchConstants#CLASS_AND_ENUM}: only look for classes and enumerations
+ * - {@link IJavaScriptSearchConstants#CLASS_AND_INTERFACE}: only look for classes and interfaces
+ * - {@link IJavaScriptSearchConstants#TYPE}: look for all types (ie. classes, interfaces, enum and annotation types)
+ *
+ * @param scope the scope to search in
+ * @param nameRequestor the requestor that collects the results of the search
+ * @param waitingPolicy one of
+ *
+ * - {@link IJavaScriptSearchConstants#FORCE_IMMEDIATE_SEARCH} if the search should start immediately
+ * - {@link IJavaScriptSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH} if the search should be cancelled if the
+ * underlying indexer has not finished indexing the workspace
+ * - {@link IJavaScriptSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if the search should wait for the
+ * underlying indexer to finish indexing the workspace
+ *
+ * @param progressMonitor the progress monitor to report progress to, or null
if no progress
+ * monitor is provided
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchAllTypeNames(
+ final char[] packageName,
+ final int packageMatchRule,
+ final char[] typeName,
+ final int typeMatchRule,
+ int searchFor,
+ IJavaScriptSearchScope scope,
+ final TypeNameRequestor nameRequestor,
+ int waitingPolicy,
+ IProgressMonitor progressMonitor) throws JavaScriptModelException {
+
+ TypeNameRequestorWrapper requestorWrapper = new TypeNameRequestorWrapper(nameRequestor);
+ this.basicEngine.searchAllTypeNames(packageName, packageMatchRule, typeName, typeMatchRule, searchFor, scope, requestorWrapper, waitingPolicy, progressMonitor);
+ }
+
+ /**
+ * Searches for all top-level types and member types in the given scope.
+ * The search can be selecting specific types (given a package name using specific match mode
+ * and/or a type name using another specific match mode).
+ *
+ * Provided {@link TypeNameMatchRequestor} requestor will collect {@link TypeNameMatch}
+ * matches found during the search.
+ *
+ *
+ * @param packageName the full name of the package of the searched types, or a prefix for this
+ * package, or a wild-carded string for this package.
+ * May be null
, then any package name is accepted.
+ * @param packageMatchRule one of
+ *
+ * - {@link SearchPattern#R_EXACT_MATCH} if the package name and type name are the full names
+ * of the searched types.
+ * - {@link SearchPattern#R_PREFIX_MATCH} if the package name and type name are prefixes of the names
+ * of the searched types.
+ * - {@link SearchPattern#R_PATTERN_MATCH} if the package name and type name contain wild-cards.
+ * - {@link SearchPattern#R_CAMELCASE_MATCH} if type name are camel case of the names of the searched types.
+ *
+ * combined with {@link SearchPattern#R_CASE_SENSITIVE},
+ * e.g. {@link SearchPattern#R_EXACT_MATCH} | {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * or {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case sensitive match is requested.
+ * @param typeName the dot-separated qualified name of the searched type (the qualification include
+ * the enclosing types if the searched type is a member type), or a prefix
+ * for this type, or a wild-carded string for this type.
+ * May be null
, then any type name is accepted.
+ * @param typeMatchRule one of
+ *
+ * - {@link SearchPattern#R_EXACT_MATCH} if the package name and type name are the full names
+ * of the searched types.
+ * - {@link SearchPattern#R_PREFIX_MATCH} if the package name and type name are prefixes of the names
+ * of the searched types.
+ * - {@link SearchPattern#R_PATTERN_MATCH} if the package name and type name contain wild-cards.
+ * - {@link SearchPattern#R_CAMELCASE_MATCH} if type name are camel case of the names of the searched types.
+ *
+ * combined with {@link SearchPattern#R_CASE_SENSITIVE},
+ * e.g. {@link SearchPattern#R_EXACT_MATCH} | {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * or {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case sensitive match is requested.
+ * @param searchFor determines the nature of the searched elements
+ *
+ * - {@link IJavaScriptSearchConstants#CLASS}: only look for classes
+ * - {@link IJavaScriptSearchConstants#INTERFACE}: only look for interfaces
+ * - {@link IJavaScriptSearchConstants#ENUM}: only look for enumeration
+ * - {@link IJavaScriptSearchConstants#ANNOTATION_TYPE}: only look for annotation type
+ * - {@link IJavaScriptSearchConstants#CLASS_AND_ENUM}: only look for classes and enumerations
+ * - {@link IJavaScriptSearchConstants#CLASS_AND_INTERFACE}: only look for classes and interfaces
+ * - {@link IJavaScriptSearchConstants#TYPE}: look for all types (ie. classes, interfaces, enum and annotation types)
+ *
+ * @param scope the scope to search in
+ * @param nameMatchRequestor the {@link TypeNameMatchRequestor requestor} that collects
+ * {@link TypeNameMatch matches} of the search.
+ * @param waitingPolicy one of
+ *
+ * - {@link IJavaScriptSearchConstants#FORCE_IMMEDIATE_SEARCH} if the search should start immediately
+ * - {@link IJavaScriptSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH} if the search should be cancelled if the
+ * underlying indexer has not finished indexing the workspace
+ * - {@link IJavaScriptSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if the search should wait for the
+ * underlying indexer to finish indexing the workspace
+ *
+ * @param progressMonitor the progress monitor to report progress to, or null
if no progress
+ * monitor is provided
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchAllTypeNames(
+ final char[] packageName,
+ final int packageMatchRule,
+ final char[] typeName,
+ final int typeMatchRule,
+ int searchFor,
+ IJavaScriptSearchScope scope,
+ final TypeNameMatchRequestor nameMatchRequestor,
+ int waitingPolicy,
+ IProgressMonitor progressMonitor) throws JavaScriptModelException {
+
+ TypeNameMatchRequestorWrapper requestorWrapper = new TypeNameMatchRequestorWrapper(nameMatchRequestor, scope);
+ this.basicEngine.searchAllTypeNames(packageName, packageMatchRule, typeName, typeMatchRule, searchFor, scope, requestorWrapper, waitingPolicy, progressMonitor);
+ }
+
+ /**
+ * Searches for all top-level types and member types in the given scope matching any of the given qualifications
+ * and type names in a case sensitive way.
+ *
+ * @param qualifications the qualified name of the package/enclosing type of the searched types.
+ * May be null
, then any package name is accepted.
+ * @param typeNames the simple names of the searched types.
+ * If this parameter is null
, then no type will be found.
+ * @param scope the scope to search in
+ * @param nameRequestor the requestor that collects the results of the search
+ * @param waitingPolicy one of
+ *
+ * - {@link IJavaScriptSearchConstants#FORCE_IMMEDIATE_SEARCH} if the search should start immediately
+ * - {@link IJavaScriptSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH} if the search should be cancelled if the
+ * underlying indexer has not finished indexing the workspace
+ * - {@link IJavaScriptSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if the search should wait for the
+ * underlying indexer to finish indexing the workspace
+ *
+ * @param progressMonitor the progress monitor to report progress to, or null
if no progress
+ * monitor is provided
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchAllTypeNames(
+ final char[][] qualifications,
+ final char[][] typeNames,
+ IJavaScriptSearchScope scope,
+ final TypeNameRequestor nameRequestor,
+ int waitingPolicy,
+ IProgressMonitor progressMonitor) throws JavaScriptModelException {
+
+ TypeNameRequestorWrapper requestorWrapper = new TypeNameRequestorWrapper(nameRequestor);
+ this.basicEngine.searchAllTypeNames(
+ qualifications,
+ typeNames,
+ SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
+ IJavaScriptSearchConstants.TYPE,
+ scope,
+ requestorWrapper,
+ waitingPolicy,
+ progressMonitor);
+ }
+
+ /**
+ * Searches for all top-level types and member types in the given scope matching any of the given qualifications
+ * and type names in a case sensitive way.
+ *
+ * Provided {@link TypeNameMatchRequestor} requestor will collect {@link TypeNameMatch}
+ * matches found during the search.
+ *
+ *
+ * @param qualifications the qualified name of the package/enclosing type of the searched types.
+ * May be null
, then any package name is accepted.
+ * @param typeNames the simple names of the searched types.
+ * If this parameter is null
, then no type will be found.
+ * @param scope the scope to search in
+ * @param nameMatchRequestor the {@link TypeNameMatchRequestor requestor} that collects
+ * {@link TypeNameMatch matches} of the search.
+ * @param waitingPolicy one of
+ *
+ * - {@link IJavaScriptSearchConstants#FORCE_IMMEDIATE_SEARCH} if the search should start immediately
+ * - {@link IJavaScriptSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH} if the search should be cancelled if the
+ * underlying indexer has not finished indexing the workspace
+ * - {@link IJavaScriptSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if the search should wait for the
+ * underlying indexer to finish indexing the workspace
+ *
+ * @param progressMonitor the progress monitor to report progress to, or null
if no progress
+ * monitor is provided
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchAllTypeNames(
+ final char[][] qualifications,
+ final char[][] typeNames,
+ IJavaScriptSearchScope scope,
+ final TypeNameMatchRequestor nameMatchRequestor,
+ int waitingPolicy,
+ IProgressMonitor progressMonitor) throws JavaScriptModelException {
+
+ TypeNameMatchRequestorWrapper requestorWrapper = new TypeNameMatchRequestorWrapper(nameMatchRequestor, scope);
+ this.basicEngine.searchAllTypeNames(
+ qualifications,
+ typeNames,
+ SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
+ IJavaScriptSearchConstants.TYPE,
+ scope,
+ requestorWrapper,
+ waitingPolicy,
+ progressMonitor);
+ }
+
+ /**
+ * Searches for all declarations of the fields accessed in the given element.
+ * The element can be a javascript unit , a source type, or a source method.
+ * Reports the field declarations using the given requestor.
+ *
+ * Consider the following code:
+ *
+ *
+ * class A {
+ * int field1;
+ * }
+ * class B extends A {
+ * String value;
+ * }
+ * class X {
+ * void test() {
+ * B b = new B();
+ * System.out.println(b.value + b.field1);
+ * };
+ * }
+ *
+ *
+ * then searching for declarations of accessed fields in method
+ * X.test()
would collect the fields
+ * B.value
and A.field1
.
+ *
+ *
+ * @param enclosingElement the method, type, or javascript unit to be searched in
+ * @param requestor a callback object to which each match is reported
+ * @param monitor the progress monitor used to report progress
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the element doesn't exist
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchDeclarationsOfAccessedFields(IJavaScriptElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaScriptModelException {
+ this.basicEngine.searchDeclarationsOfAccessedFields(enclosingElement, requestor, monitor);
+ }
+
+ /**
+ * Searches for all declarations of the types referenced in the given element.
+ * The element can be a javascript unit , a source type, or a source method.
+ * Reports the type declarations using the given requestor.
+ *
+ * Consider the following code:
+ *
+ *
+ * class A {
+ * }
+ * class B extends A {
+ * }
+ * interface I {
+ * int VALUE = 0;
+ * }
+ * class X {
+ * void test() {
+ * B b = new B();
+ * this.foo(b, I.VALUE);
+ * };
+ * }
+ *
+ *
+ * then searching for declarations of referenced types in method X.test()
+ * would collect the class B
and the interface I
.
+ *
+ *
+ * @param enclosingElement the method, type, or javascript unit to be searched in
+ * @param requestor a callback object to which each match is reported
+ * @param monitor the progress monitor used to report progress
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the element doesn't exist
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchDeclarationsOfReferencedTypes(IJavaScriptElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaScriptModelException {
+ this.basicEngine.searchDeclarationsOfReferencedTypes(enclosingElement, requestor, monitor);
+ }
+
+ /**
+ * Searches for all declarations of the methods invoked in the given element.
+ * The element can be a javascript unit , a source type, or a source method.
+ * Reports the method declarations using the given requestor.
+ *
+ * Consider the following code:
+ *
+ *
+ * class A {
+ * void foo() {};
+ * void bar() {};
+ * }
+ * class B extends A {
+ * void foo() {};
+ * }
+ * class X {
+ * void test() {
+ * A a = new B();
+ * a.foo();
+ * B b = (B)a;
+ * b.bar();
+ * };
+ * }
+ *
+ *
+ * then searching for declarations of sent messages in method
+ * X.test()
would collect the methods
+ * A.foo()
, B.foo()
, and A.bar()
.
+ *
+ *
+ * @param enclosingElement the method, type, or javascript unit to be searched in
+ * @param requestor a callback object to which each match is reported
+ * @param monitor the progress monitor used to report progress
+ * @exception JavaScriptModelException if the search failed. Reasons include:
+ *
+ * - the element doesn't exist
+ * - the includepath is incorrectly set
+ *
+ *
+ */
+ public void searchDeclarationsOfSentMessages(IJavaScriptElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaScriptModelException {
+ this.basicEngine.searchDeclarationsOfSentMessages(enclosingElement, requestor, monitor);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchMatch.java
new file mode 100644
index 0000000..498805c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchMatch.java
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.internal.core.JavaElement;
+
+/**
+ * A search match represents the result of a search query.
+ *
+ * Search matches may be accurate (A_ACCURATE
) or they might be
+ * merely potential matches (A_INACCURATE
). The latter occurs when
+ * a compile-time problem prevents the search engine from completely resolving
+ * the match.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * @see SearchEngine#search(SearchPattern, SearchParticipant[], IJavaScriptSearchScope, SearchRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class SearchMatch {
+
+ /**
+ * The search result corresponds an exact match of the search pattern.
+ *
+ * @see #getAccuracy()
+ */
+ public static final int A_ACCURATE = 0;
+
+ /**
+ * The search result is potentially a match for the search pattern,
+ * but the search engine is unable to fully check it (for example, because
+ * there are errors in the code or the includepath are not correctly set).
+ *
+ * @see #getAccuracy()
+ */
+ public static final int A_INACCURATE = 1;
+
+ private Object element;
+ private int length;
+ private int offset;
+
+ private int accuracy;
+ private SearchParticipant participant;
+ private IResource resource;
+
+ private boolean insideDocComment = false;
+
+ // store the rule used while reporting the match
+ private final static int ALL_GENERIC_FLAVORS = SearchPattern.R_FULL_MATCH |
+ SearchPattern.R_EQUIVALENT_MATCH |
+ SearchPattern.R_ERASURE_MATCH;
+ private int rule = ALL_GENERIC_FLAVORS;
+
+ // store other necessary information
+ private boolean raw = false;
+ private boolean implicit = false;
+
+ /**
+ * Creates a new search match.
+ *
+ * Note that isInsideDocComment()
defaults to false.
+ *
+ *
+ * @param element the element that encloses or corresponds to the match,
+ * or null
if none
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element, or null
if none
+ */
+ public SearchMatch(
+ IJavaScriptElement element,
+ int accuracy,
+ int offset,
+ int length,
+ SearchParticipant participant,
+ IResource resource) {
+ this.element = element;
+ this.offset = offset;
+ this.length = length;
+ this.accuracy = accuracy & A_INACCURATE;
+ if (accuracy > A_INACCURATE) {
+ int genericFlavors = accuracy & ALL_GENERIC_FLAVORS;
+ if (genericFlavors > 0) {
+ this.rule &= ~ALL_GENERIC_FLAVORS; // reset generic flavors
+ }
+ this.rule |= accuracy & ~A_INACCURATE; // accuracy may have also some rule information
+ }
+ this.participant = participant;
+ this.resource = resource;
+ }
+
+ /**
+ * Returns the accuracy of this search match.
+ *
+ * @return one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ */
+ public final int getAccuracy() {
+ return this.accuracy;
+ }
+
+ /**
+ * Returns the element of this search match.
+ * In case of a reference match, this is the inner-most enclosing element of the reference.
+ * In case of a declaration match, this is the declaration.
+ *
+ * @return the element of the search match, or null
if none
+ */
+ public final Object getElement() {
+ return this.element;
+ }
+
+ /**
+ * Returns the length of this search match.
+ *
+ * @return the length of this search match, or -1 if unknown
+ */
+ public final int getLength() {
+ return this.length;
+ }
+
+ /**
+ * Returns the offset of this search match.
+ *
+ * @return the offset of this search match, or -1 if unknown
+ */
+ public final int getOffset() {
+ return this.offset;
+ }
+
+ /**
+ * Returns the search participant which issued this search match.
+ *
+ * @return the participant which issued this search match
+ */
+ public final SearchParticipant getParticipant() {
+ return this.participant;
+ }
+
+ /**
+ * Returns the resource containing this search match.
+ *
+ * @return the resource of the match, or null
if none
+ */
+ public final IResource getResource() {
+ return this.resource;
+ }
+
+ /**
+ * Returns the rule used while creating the match.
+ *
+ * @return one of {@link SearchPattern#R_FULL_MATCH}, {@link SearchPattern#R_EQUIVALENT_MATCH}
+ * or {@link SearchPattern#R_ERASURE_MATCH}
+ *
+ */
+ public final int getRule() {
+ return this.rule;
+ }
+
+ /**
+ * Returns whether match element is compatible with searched pattern or not.
+ * Note that equivalent matches are also erasure ones.
+ *
+ * @return true
if match element is compatible
+ * false
otherwise
+ *
+ */
+ public final boolean isEquivalent() {
+ return isErasure() && (this.rule & SearchPattern.R_EQUIVALENT_MATCH) != 0;
+ }
+
+ /**
+ * Returns whether match element only has same erasure than searched pattern or not.
+ * Note that this is always true for both generic and non-generic element as soon
+ * as the accuracy is accurate.
+ *
+ * @return true
if match element has same erasure
+ * false
otherwise
+ *
+ */
+ public final boolean isErasure() {
+ return (this.rule & SearchPattern.R_ERASURE_MATCH) != 0;
+ }
+
+ /**
+ * Returns whether element matches exactly searched pattern or not.
+ * Note that exact matches are also erasure and equivalent ones.
+ *
+ * @return true
if match is exact
+ * false
otherwise
+ *
+ */
+ public final boolean isExact() {
+ return isEquivalent() && (this.rule & SearchPattern.R_FULL_MATCH) != 0;
+ }
+
+ /**
+ * Returns whether the associated element is implicit or not.
+ *
+ * Note that this piece of information is currently only implemented
+ * for implicit member pair value in annotation.
+ *
+ * @return true
if this match is associated to an implicit
+ * element and false
otherwise
+ *
+ */
+ public final boolean isImplicit() {
+ return this.implicit;
+ }
+
+ /**
+ * Returns whether the associated element is a raw type/method or not.
+ *
+ * @return true
if this match is associated to a raw
+ * type or method and false
otherwise
+ *
+ */
+ public final boolean isRaw() {
+ return this.raw;
+ }
+
+ /**
+ * Returns whether this search match is inside a doc comment of a Java
+ * source file.
+ *
+ * @return true
if this search match is inside a doc
+ * comment, and false
otherwise
+ */
+ public final boolean isInsideDocComment() {
+ // default is outside a doc comment
+ return this.insideDocComment;
+ }
+
+ /**
+ * Sets the accuracy of this match.
+ *
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ */
+ public final void setAccuracy (int accuracy) {
+ this.accuracy = accuracy;
+ }
+
+ /**
+ * Sets the element of this search match.
+ *
+ * @param element the element that encloses or corresponds to the match,
+ * or null
if none
+ */
+ public final void setElement (Object element) {
+ this.element = element;
+ }
+
+ /**
+ * Sets whether this search match is inside a doc comment of a Java
+ * source file.
+ *
+ * @param insideDoc true
if this search match is inside a doc
+ * comment, and false
otherwise
+ */
+ public final void setInsideDocComment (boolean insideDoc) {
+ this.insideDocComment = insideDoc;
+ }
+
+ /**
+ * Sets whether the associated element is implicit or not.
+ * Typically, this is the case when match is on an implicit constructor
+ * or an implicit member pair value in annotation.
+ *
+ * @param implicit true
if this match is associated to an implicit
+ * element and false
otherwise
+ *
+ */
+ public final void setImplicit(boolean implicit) {
+ this.implicit = implicit;
+ }
+
+ /**
+ * Sets the length of this search match.
+ *
+ * @param length the length of the match, or -1 if unknown
+ */
+ public final void setLength(int length) {
+ this.length = length;
+ }
+
+ /**
+ * Sets the offset of this search match.
+ *
+ * @param offset the offset the match starts at, or -1 if unknown
+ */
+ public final void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+ /**
+ * Sets the participant of this match.
+ *
+ * @param participant the search participant that created this match
+ */
+ public final void setParticipant (SearchParticipant participant) {
+ this.participant = participant;
+ }
+
+ /**
+ * Sets the resource of this match.
+ *
+ * @param resource the resource of the match, or null
if none
+ */
+ public final void setResource (IResource resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Set the rule used while reporting the match.
+ *
+ * @param rule one of {@link SearchPattern#R_FULL_MATCH}, {@link SearchPattern#R_EQUIVALENT_MATCH}
+ * or {@link SearchPattern#R_ERASURE_MATCH}
+ *
+ */
+ public final void setRule(int rule) {
+ this.rule = rule;
+ }
+
+ /**
+ * Set whether the associated element is a raw type/method or not.
+ *
+ * @param raw true
if this search match is associated to a raw
+ * type or method and false
otherwise
+ *
+ */
+ public final void setRaw(boolean raw) {
+ this.raw = raw;
+ }
+
+ /* (non-javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("Search match"); //$NON-NLS-1$
+ buffer.append("\n accuracy="); //$NON-NLS-1$
+ buffer.append(this.accuracy == A_ACCURATE ? "ACCURATE" : "INACCURATE"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append("\n rule="); //$NON-NLS-1$
+ if ((this.rule & SearchPattern.R_FULL_MATCH) != 0) {
+ buffer.append("EXACT"); //$NON-NLS-1$
+ } else if ((this.rule & SearchPattern.R_EQUIVALENT_MATCH) != 0) {
+ buffer.append("EQUIVALENT"); //$NON-NLS-1$
+ } else if ((this.rule & SearchPattern.R_ERASURE_MATCH) != 0) {
+ buffer.append("ERASURE"); //$NON-NLS-1$
+ }
+ buffer.append("\n raw="); //$NON-NLS-1$
+ buffer.append(this.raw);
+ buffer.append("\n offset="); //$NON-NLS-1$
+ buffer.append(this.offset);
+ buffer.append("\n length="); //$NON-NLS-1$
+ buffer.append(this.length);
+ if (this.element != null) {
+ buffer.append("\n element="); //$NON-NLS-1$
+ buffer.append(((JavaElement)getElement()).toStringWithAncestors());
+ }
+ buffer.append("\n"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchParticipant.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchParticipant.java
new file mode 100644
index 0000000..939165f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchParticipant.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.jsdt.internal.core.JavaModel;
+import org.eclipse.wst.jsdt.internal.core.JavaModelManager;
+import org.eclipse.wst.jsdt.internal.core.search.indexing.IndexManager;
+
+/**
+ * A search participant describes a particular extension to a generic search
+ * mechanism, permitting combined search actions which will involve all required
+ * participants.
+ *
+ * A search participant is involved in the indexing phase and in the search phase.
+ * The indexing phase consists in taking one or more search documents, parse them, and
+ * add index entries in an index chosen by the participant. An index is identified by a
+ * path on disk.
+ * The search phase consists in selecting the indexes corresponding to a search pattern
+ * and a search scope, from these indexes the search infrastructure extracts the document paths
+ * that match the search pattern asking the search participant for the corresponding document,
+ * finally the search participant is asked to locate the matches precisely in these search documents.
+ *
+ *
+ * This class is intended to be subclassed by clients. During the indexing phase,
+ * a subclass will be called with the following requests in order:
+ *
+ * - {@link #scheduleDocumentIndexing(SearchDocument, IPath)}
+ * - {@link #indexDocument(SearchDocument, IPath)}
+ *
+ * During the search phase, a subclass will be called with the following requests in order:
+ *
+ * - {@link #selectIndexes(SearchPattern, IJavaScriptSearchScope)}
+ * - one or more {@link #getDocument(String)}
+ * - {@link #locateMatches(SearchDocument[], SearchPattern, IJavaScriptSearchScope, SearchRequestor, IProgressMonitor)}
+ *
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class SearchParticipant {
+
+ /**
+ * Creates a new search participant.
+ */
+ protected SearchParticipant() {
+ // do nothing
+ }
+
+ /**
+ * Notification that this participant's help is needed in a search.
+ *
+ * This method should be re-implemented in subclasses that need to do something
+ * when the participant is needed in a search.
+ *
+ */
+ public void beginSearching() {
+ // do nothing
+ }
+
+ /**
+ * Notification that this participant's help is no longer needed.
+ *
+ * This method should be re-implemented in subclasses that need to do something
+ * when the participant is no longer needed in a search.
+ *
+ */
+ public void doneSearching() {
+ // do nothing
+ }
+
+ /**
+ * Returns a displayable name of this search participant.
+ *
+ * This method should be re-implemented in subclasses that need to
+ * display a meaningfull name.
+ *
+ *
+ * @return the displayable name of this search participant
+ */
+ public String getDescription() {
+ return "Search participant"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns a search document for the given path.
+ * The given document path is a string that uniquely identifies the document.
+ * Most of the time it is a workspace-relative path, but it can also be a file system path, or a path inside a zip file.
+ *
+ * Implementors of this method can either create an instance of their own subclass of
+ * {@link SearchDocument} or return an existing instance of such a subclass.
+ *
+ *
+ * @param documentPath the path of the document.
+ * @return a search document
+ */
+ public abstract SearchDocument getDocument(String documentPath);
+
+ /**
+ * Indexes the given document in the given index. A search participant
+ * asked to index a document should parse it and call
+ * {@link SearchDocument#addIndexEntry(char[], char[])} as many times as
+ * needed to add index entries to the index. If delegating to another
+ * participant, it should use the original index location (and not the
+ * delegatee's one). In the particular case of delegating to the default
+ * search participant (see {@link SearchEngine#getDefaultSearchParticipant()}),
+ * the provided document's path must be a path ending with one of the
+ * {@link org.eclipse.wst.jsdt.core.JavaScriptCore#getJavaScriptLikeExtensions() Java-like extensions}
+ * or with '.class'.
+ *
+ * The given index location must represent a path in the file system to a file that
+ * either already exists or is going to be created. If it exists, it must be an index file,
+ * otherwise its data might be overwritten.
+ *
+ * Clients are not expected to call this method.
+ *
+ *
+ * @param document the document to index
+ * @param indexLocation the location in the file system to the index
+ */
+ public abstract void indexDocument(SearchDocument document, IPath indexLocation);
+
+ /**
+ * Locates the matches in the given documents using the given search pattern
+ * and search scope, and reports them to the givenn search requestor. This
+ * method is called by the search engine once it has search documents
+ * matching the given pattern in the given search scope.
+ *
+ * Note that a participant (e.g. a JSP participant) can pre-process the contents of the given documents,
+ * create its own documents whose contents are JavaScript javascript unit s and delegate the match location
+ * to the default participant (see {@link SearchEngine#getDefaultSearchParticipant()}). Passing its own
+ * {@link SearchRequestor} this particpant can then map the match positions back to the original
+ * contents, create its own matches and report them to the original requestor.
+ *
+ * Implementors of this method should check the progress monitor
+ * for cancelation when it is safe and appropriate to do so. The cancelation
+ * request should be propagated to the caller by throwing
+ * OperationCanceledException
.
+ *
+ *
+ * @param documents the documents to locate matches in
+ * @param pattern the search pattern to use when locating matches
+ * @param scope the scope to limit the search to
+ * @param requestor the requestor to report matches to
+ * @param monitor the progress monitor to report progress to,
+ * or null
if no progress should be reported
+ * @throws CoreException if the requestor had problem accepting one of the matches
+ */
+ public abstract void locateMatches(SearchDocument[] documents, SearchPattern pattern, IJavaScriptSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Removes the index for a given path.
+ *
+ * The given index location must represent a path in the file system to a file that
+ * already exists and must be an index file, otherwise nothing will be done.
+ *
+ * It is strongly recommended to use this method instead of deleting file directly
+ * otherwise cached index will not be removed.
+ *
+ *
+ * @param indexLocation the location in the file system to the index
+ *
+ */
+ public void removeIndex(IPath indexLocation){
+ IndexManager manager = JavaModelManager.getJavaModelManager().getIndexManager();
+ manager.removeIndexPath(indexLocation);
+ }
+
+ /**
+ * Schedules the indexing of the given document.
+ * Once the document is ready to be indexed,
+ * {@link #indexDocument(SearchDocument, IPath) indexDocument(document, indexPath)}
+ * will be called in a different thread than the caller's thread.
+ *
+ * The given index location must represent a path in the file system to a file that
+ * either already exists or is going to be created. If it exists, it must be an index file,
+ * otherwise its data might be overwritten.
+ *
+ * When the index is no longer needed, clients should use {@link #removeIndex(IPath) }
+ * to discard it.
+ *
+ *
+ * @param document the document to index
+ * @param indexLocation the location on the file system of the index
+ */
+ public final void scheduleDocumentIndexing(SearchDocument document, IPath indexLocation) {
+ IPath documentPath = new Path(document.getPath());
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ Object file = JavaModel.getTarget(root, documentPath, true);
+ IPath containerPath = documentPath;
+ if (file instanceof IResource) {
+ containerPath = ((IResource)file).getProject().getFullPath();
+ } else if (file == null) {
+ containerPath = documentPath.removeLastSegments(1);
+ }
+ IndexManager manager = JavaModelManager.getJavaModelManager().getIndexManager();
+ // TODO (frederic) should not have to create index manually, should expose API that recreates index instead
+ manager.ensureIndexExists(indexLocation, containerPath);
+ manager.scheduleDocumentIndexing(document, containerPath, indexLocation, this);
+ }
+
+ /**
+ * Returns the collection of index locations to consider when performing the
+ * given search query in the given scope. The search engine calls this
+ * method before locating matches.
+ *
+ * An index location represents a path in the file system to a file that holds index information.
+ *
+ * Clients are not expected to call this method.
+ *
+ *
+ * @param query the search pattern to consider
+ * @param scope the given search scope
+ * @return the collection of index paths to consider
+ */
+ public abstract IPath[] selectIndexes(SearchPattern query, IJavaScriptSearchScope scope);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchPattern.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchPattern.java
new file mode 100644
index 0000000..1b21032
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/SearchPattern.java
@@ -0,0 +1,1921 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.wst.jsdt.core.IField;
+import org.eclipse.wst.jsdt.core.IFunction;
+import org.eclipse.wst.jsdt.core.IImportDeclaration;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IMember;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.Signature;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.wst.jsdt.internal.core.LocalVariable;
+import org.eclipse.wst.jsdt.internal.core.search.indexing.IIndexConstants;
+import org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.FieldPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.InternalSearchPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.LocalVariablePattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.MatchLocator;
+import org.eclipse.wst.jsdt.internal.core.search.matching.MethodPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.OrPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.PackageDeclarationPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.PackageReferencePattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.QualifiedTypeDeclarationPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.SuperTypeReferencePattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.TypeDeclarationPattern;
+import org.eclipse.wst.jsdt.internal.core.search.matching.TypeReferencePattern;
+
+
+/**
+ * A search pattern defines how search results are found. Use SearchPattern.createPattern
+ * to create a search pattern.
+ *
+ * Search patterns are used during the search phase to decode index entries that were added during the indexing phase
+ * (see {@link SearchDocument#addIndexEntry(char[], char[])}). When an index is queried, the
+ * index categories and keys to consider are retrieved from the search pattern using {@link #getIndexCategories()} and
+ * {@link #getIndexKey()}, as well as the match rule (see {@link #getMatchRule()}). A blank pattern is
+ * then created (see {@link #getBlankPattern()}). This blank pattern is used as a record as follows.
+ * For each index entry in the given index categories and that starts with the given key, the blank pattern is fed using
+ * {@link #decodeIndexKey(char[])}. The original pattern is then asked if it matches the decoded key using
+ * {@link #matchesDecodedKey(SearchPattern)}. If it matches, a search doument is created for this index entry
+ * using {@link SearchParticipant#getDocument(String)}.
+ *
+ *
+ * This class is intended to be subclassed by clients. A default behavior is provided for each of the methods above, that
+ * clients can ovveride if they wish.
+ *
+ * @see #createPattern(org.eclipse.wst.jsdt.core.IJavaScriptElement, int)
+ * @see #createPattern(String, int, int, int)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class SearchPattern extends InternalSearchPattern {
+
+ // Rules for pattern matching: (exact, prefix, pattern) [ | case sensitive]
+ /**
+ * Match rule: The search pattern matches exactly the search result,
+ * that is, the source of the search result equals the search pattern.
+ */
+ public static final int R_EXACT_MATCH = 0;
+
+ /**
+ * Match rule: The search pattern is a prefix of the search result.
+ */
+ public static final int R_PREFIX_MATCH = 0x0001;
+
+ /**
+ * Match rule: The search pattern contains one or more wild cards ('*' or '?').
+ * A '*' wild-card can replace 0 or more characters in the search result.
+ * A '?' wild-card replaces exactly 1 character in the search result.
+ */
+ public static final int R_PATTERN_MATCH = 0x0002;
+
+ /**
+ * Match rule: The search pattern contains a regular expression.
+ */
+ public static final int R_REGEXP_MATCH = 0x0004;
+
+ /**
+ * Match rule: The search pattern matches the search result only if cases are the same.
+ * Can be combined to previous rules, e.g. {@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE}
+ */
+ public static final int R_CASE_SENSITIVE = 0x0008;
+
+ /**
+ * Match rule: The search pattern matches search results as raw/parameterized types/methods with same erasure.
+ * This mode has no effect on other javascript elements search.
+ * Type search example:
+ *
+ * - pattern:
List<Exception>
+ * - match:
List<Object>
+ *
+ * Method search example:
+ *
+ * - declaration:
<T>foo(T t)
+ * - pattern:
<Exception>foo(new Exception())
+ * - match:
<Object>foo(new Object())
+ *
+ * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_ERASURE_MATCH}
+ * This rule is not activated by default, so raw types or parameterized types with same erasure will not be found
+ * for pattern List<String>,
+ * Note that with this pattern, the match selection will be only on the erasure even for parameterized types.
+ *
+ */
+ public static final int R_ERASURE_MATCH = 0x0010;
+
+ /**
+ * Match rule: The search pattern matches search results as raw/parameterized types/methods with equivalent type parameters.
+ * This mode has no effect on other javascript elements search.
+ * Type search example:
+ *
+ * - pattern:
List<Exception>
+ * - match:
+ *
+ * List<? extends Throwable>
+ * List<? super RuntimeException>
+ * List<?>
+ *
+ *
+ *
+ * Method search example:
+ *
+ * - declaration:
<T>foo(T t)
+ * - pattern:
<Exception>foo(new Exception())
+ * - match:
+ *
+ * <? extends Throwable>foo(new Exception())
+ * <? super RuntimeException>foo(new Exception())
+ * foo(new Exception())
+ *
+ *
+ * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_EQUIVALENT_MATCH}
+ * This rule is not activated by default, so raw types or equivalent parameterized types will not be found
+ * for pattern List<String>,
+ * This mode is overridden by {@link #R_ERASURE_MATCH} as erasure matches obviously include equivalent ones.
+ * That means that pattern with rule set to {@link #R_EQUIVALENT_MATCH} | {@link #R_ERASURE_MATCH}
+ * will return same results than rule only set with {@link #R_ERASURE_MATCH}.
+ *
+ */
+ public static final int R_EQUIVALENT_MATCH = 0x0020;
+
+ /**
+ * Match rule: The search pattern matches exactly the search result,
+ * that is, the source of the search result equals the search pattern.
+ *
+ */
+ public static final int R_FULL_MATCH = 0x0040;
+
+ /**
+ * Match rule: The search pattern contains a Camel Case expression.
+ *
+ * Examples:
+ *
+ * NPE
type string pattern will match
+ * NullPointerException
and NpPermissionException
types,
+ * NuPoEx
type string pattern will only match
+ * NullPointerException
type.
+ *
+ * @see CharOperation#camelCaseMatch(char[], char[]) for a detailed explanation
+ * of Camel Case matching.
+ *
+ * Can be combined to {@link #R_PREFIX_MATCH} match rule. For example,
+ * when prefix match rule is combined with Camel Case match rule,
+ * "nPE"
pattern will match nPException
.
+ *
+ * Match rule {@link #R_PATTERN_MATCH} may also be combined but both rules
+ * will not be used simultaneously as they are mutually exclusive.
+ * Used match rule depends on whether string pattern contains specific pattern
+ * characters (e.g. '*' or '?') or not. If it does, then only Pattern match rule
+ * will be used, otherwise only Camel Case match will be used.
+ * For example, with "NPE"
string pattern, search will only use
+ * Camel Case match rule, but with N*P*E*
string pattern, it will
+ * use only Pattern match rule.
+ *
+ *
+ */
+ public static final int R_CAMELCASE_MATCH = 0x0080;
+
+ private static final int MODE_MASK = R_EXACT_MATCH | R_PREFIX_MATCH | R_PATTERN_MATCH | R_REGEXP_MATCH;
+
+ private int matchRule;
+
+/**
+ * Creates a search pattern with the rule to apply for matching index keys.
+ * It can be exact match, prefix match, pattern match or regexp match.
+ * Rule can also be combined with a case sensitivity flag.
+ *
+ * @param matchRule one of {@link #R_EXACT_MATCH}, {@link #R_PREFIX_MATCH}, {@link #R_PATTERN_MATCH},
+ * {@link #R_REGEXP_MATCH}, {@link #R_CAMELCASE_MATCH} combined with one of following values:
+ * {@link #R_CASE_SENSITIVE}, {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH}.
+ * e.g. {@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * {@link #R_PREFIX_MATCH} if a prefix non case sensitive match is requested or {@link #R_EXACT_MATCH} | {@link #R_ERASURE_MATCH}
+ * if a non case sensitive and erasure match is requested.
+ * Note that {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH} have no effect
+ * on non-generic types/methods search.
+ * Note also that default behavior for generic types/methods search is to find exact matches.
+ */
+public SearchPattern(int matchRule) {
+ this.matchRule = matchRule;
+ // Set full match implicit mode
+ if ((matchRule & (R_EQUIVALENT_MATCH | R_ERASURE_MATCH )) == 0) {
+ this.matchRule |= R_FULL_MATCH;
+ }
+}
+
+/**
+ * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
+ * CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Examples:
+ *
+ *
+ * pattern = "NPE"
+ * name = NullPointerException / NoPermissionException
+ * result => true
+ *
+ *
+ *
+ * pattern = "NuPoEx"
+ * name = NullPointerException
+ * result => true
+ *
+ *
+ *
+ * pattern = "npe"
+ * name = NullPointerException
+ * result => false
+ *
+ *
+ *
+ * @see CharOperation#camelCaseMatch(char[], char[])
+ * Implementation has been entirely copied from this method except for array lengthes
+ * which were obviously replaced with calls to {@link String#length()}.
+ *
+ * @param pattern the given pattern
+ * @param name the given name
+ * @return true if the pattern matches the given name, false otherwise
+ *
+ */
+public static final boolean camelCaseMatch(String pattern, String name) {
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (name == null)
+ return false; // null name cannot match
+
+ return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name.length());
+}
+
+/**
+ * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.
+ * CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
+ * Can match only subset of name/pattern, considering end positions as non-inclusive.
+ * The subpattern is defined by the patternStart and patternEnd positions.
+ *
+ * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
+ * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
+ * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
+ * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
+ * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
+ * names follow the lower CamelCase convention.
+ *
+ * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
+ * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
+ * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
+ *
+ * Examples:
+ *
+ *
+ * pattern = "NPE"
+ * patternStart = 0
+ * patternEnd = 3
+ * name = NullPointerException
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ *
+ *
+ *
+ * pattern = "NPE"
+ * patternStart = 0
+ * patternEnd = 3
+ * name = NoPermissionException
+ * nameStart = 0
+ * nameEnd = 21
+ * result => true
+ *
+ *
+ *
+ * pattern = "NuPoEx"
+ * patternStart = 0
+ * patternEnd = 6
+ * name = NullPointerException
+ * nameStart = 0
+ * nameEnd = 20
+ * result => true
+ *
+ *
+ *
+ * pattern = "NuPoEx"
+ * patternStart = 0
+ * patternEnd = 6
+ * name = NoPermissionException
+ * nameStart = 0
+ * nameEnd = 21
+ * result => false
+ *
+ *
+ *
+ * pattern = "npe"
+ * patternStart = 0
+ * patternEnd = 3
+ * name = NullPointerException
+ * nameStart = 0
+ * nameEnd = 20
+ * result => false
+ *
+ *
+ *
+ * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int)
+ * Implementation has been entirely copied from this method except for array lengthes
+ * which were obviously replaced with calls to {@link String#length()} and
+ * for array direct access which were replaced with calls to {@link String#charAt(int)}.
+ *
+ * @param pattern the given pattern
+ * @param patternStart the start index of the pattern, inclusive
+ * @param patternEnd the end index of the pattern, exclusive
+ * @param name the given name
+ * @param nameStart the start index of the name, inclusive
+ * @param nameEnd the end index of the name, exclusive
+ * @return true if a sub-pattern matches the subpart of the given name, false otherwise
+ *
+ */
+public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd) {
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ if (patternEnd < 0) patternEnd = pattern.length();
+ if (nameEnd < 0) nameEnd = name.length();
+
+ if (patternEnd <= patternStart) return nameEnd <= nameStart;
+ if (nameEnd <= nameStart) return false;
+ // check first pattern char
+ if (name.charAt(nameStart) != pattern.charAt(patternStart)) {
+ // first char must strictly match (upper/lower)
+ return false;
+ }
+
+ char patternChar, nameChar;
+ int iPattern = patternStart;
+ int iName = nameStart;
+
+ // Main loop is on pattern characters
+ while (true) {
+
+ iPattern++;
+ iName++;
+
+ if (iPattern == patternEnd) {
+ // We have exhausted pattern, so it's a match
+ return true;
+ }
+
+ if (iName == nameEnd){
+ // We have exhausted name (and not pattern), so it's not a match
+ return false;
+ }
+
+ // For as long as we're exactly matching, bring it on (even if it's a lower case character)
+ if ((patternChar = pattern.charAt(iPattern)) == name.charAt(iName)) {
+ continue;
+ }
+
+ // If characters are not equals, then it's not a match if patternChar is lowercase
+ if (patternChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & ScannerHelper.C_UPPER_LETTER) == 0) {
+ return false;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar)) {
+ return false;
+ }
+
+ // patternChar is uppercase, so let's find the next uppercase in name
+ while (true) {
+ if (iName == nameEnd){
+ // We have exhausted name (and not pattern), so it's not a match
+ return false;
+ }
+
+ nameChar = name.charAt(iName);
+
+ if (nameChar < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & (ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_SPECIAL | ScannerHelper.C_DIGIT)) != 0) {
+ // nameChar is lowercase
+ iName++;
+ // nameChar is uppercase...
+ } else if (patternChar != nameChar) {
+ //.. and it does not match patternChar, so it's not a match
+ return false;
+ } else {
+ //.. and it matched patternChar. Back to the big loop
+ break;
+ }
+ }
+ else if (Character.isJavaIdentifierPart(nameChar) && !Character.isUpperCase(nameChar)) {
+ // nameChar is lowercase
+ iName++;
+ // nameChar is uppercase...
+ } else if (patternChar != nameChar) {
+ //.. and it does not match patternChar, so it's not a match
+ return false;
+ } else {
+ //.. and it matched patternChar. Back to the big loop
+ break;
+ }
+ }
+ // At this point, either name has been exhausted, or it is at an uppercase letter.
+ // Since pattern is also at an uppercase letter
+ }
+}
+
+/**
+ * Returns a search pattern that combines the given two patterns into an
+ * "and" pattern. The search result will match both the left pattern and
+ * the right pattern.
+ *
+ * @param leftPattern the left pattern
+ * @param rightPattern the right pattern
+ * @return an "and" pattern
+ */
+public static SearchPattern createAndPattern(SearchPattern leftPattern, SearchPattern rightPattern) {
+ return MatchLocator.createAndPattern(leftPattern, rightPattern);
+}
+
+/**
+ * Field pattern are formed by [declaringType.]name[ type]
+ * e.g. java.lang.String.serialVersionUID long
+ * field*
+ */
+private static SearchPattern createFieldPattern(String patternString, int limitTo, int matchRule,boolean isVar) {
+
+ Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+ scanner.setSource(patternString.toCharArray());
+ final int InsideDeclaringPart = 1;
+ final int InsideType = 2;
+ int lastToken = -1;
+
+ String declaringType = null, fieldName = null;
+ String type = null;
+ int mode = InsideDeclaringPart;
+ int token;
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ while (token != TerminalTokens.TokenNameEOF) {
+ switch(mode) {
+ // read declaring type and fieldName
+ case InsideDeclaringPart :
+ switch (token) {
+ case TerminalTokens.TokenNameDOT:
+ if (declaringType == null) {
+ if (fieldName == null) return null;
+ declaringType = fieldName;
+ } else {
+ String tokenSource = scanner.getCurrentTokenString();
+ declaringType += tokenSource + fieldName;
+ }
+ fieldName = null;
+ break;
+ case TerminalTokens.TokenNameWHITESPACE:
+ if (!(TerminalTokens.TokenNameWHITESPACE == lastToken || TerminalTokens.TokenNameDOT == lastToken))
+ mode = InsideType;
+ break;
+ default: // all other tokens are considered identifiers (see bug 21763 Problem in JavaScript search [search])
+ if (fieldName == null)
+ fieldName = scanner.getCurrentTokenString();
+ else
+ fieldName += scanner.getCurrentTokenString();
+ }
+ break;
+ // read type
+ case InsideType:
+ switch (token) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ break;
+ default: // all other tokens are considered identifiers (see bug 21763 Problem in JavaScript search [search])
+ if (type == null)
+ type = scanner.getCurrentTokenString();
+ else
+ type += scanner.getCurrentTokenString();
+ }
+ break;
+ }
+ lastToken = token;
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ }
+ if (fieldName == null) return null;
+
+ char[] fieldNameChars = fieldName.toCharArray();
+ if (fieldNameChars.length == 1 && fieldNameChars[0] == '*') fieldNameChars = null;
+
+ char[] declaringTypeQualification = null, declaringTypeSimpleName = null;
+ char[] typeQualification = null, typeSimpleName = null;
+
+ // extract declaring type infos
+ if (declaringType != null) {
+ char[] declaringTypePart = declaringType.toCharArray();
+ int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart);
+ if (lastDotPosition >= 0) {
+ declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition);
+ if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*')
+ declaringTypeQualification = null;
+ declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length);
+ } else {
+ declaringTypeSimpleName = declaringTypePart;
+ }
+ if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*')
+ declaringTypeSimpleName = null;
+ }
+ // extract type infos
+ if (type != null) {
+ char[] typePart = type.toCharArray();
+ int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
+ if (lastDotPosition >= 0) {
+ typeQualification = CharOperation.subarray(typePart, 0, lastDotPosition);
+ if (typeQualification.length == 1 && typeQualification[0] == '*') {
+ typeQualification = null;
+ } else {
+ // prefix with a '*' as the full qualification could be bigger (because of an import)
+ typeQualification = CharOperation.concat(IIndexConstants.ONE_STAR, typeQualification);
+ }
+ typeSimpleName = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length);
+ } else {
+ typeSimpleName = typePart;
+ }
+ if (typeSimpleName.length == 1 && typeSimpleName[0] == '*')
+ typeSimpleName = null;
+ }
+ // Create field pattern
+ boolean findDeclarations = false;
+ boolean readAccess = false;
+ boolean writeAccess = false;
+ switch (limitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ findDeclarations = true;
+ break;
+ case IJavaScriptSearchConstants.REFERENCES :
+ readAccess = true;
+ writeAccess = true;
+ break;
+ case IJavaScriptSearchConstants.READ_ACCESSES :
+ readAccess = true;
+ break;
+ case IJavaScriptSearchConstants.WRITE_ACCESSES :
+ writeAccess = true;
+ break;
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ findDeclarations = true;
+ readAccess = true;
+ writeAccess = true;
+ break;
+ }
+ return new FieldPattern(
+ findDeclarations,
+ readAccess,
+ writeAccess,
+ isVar,
+ fieldNameChars,
+ declaringTypeQualification,
+ declaringTypeSimpleName,
+ typeQualification,
+ typeSimpleName,
+ matchRule,null);
+}
+
+/**
+ * Method pattern are formed by:
+ * [declaringType '.'] ['<' typeArguments '>'] selector ['(' parameterTypes ')'] [returnType]
+ *
e.g.
+ * - java.lang.Runnable.run() void
+ * - main(*)
+ * - <String>toArray(String[])
+ *
+ * Constructor pattern are formed by:
+ * [declaringQualification '.'] ['<' typeArguments '>'] type ['(' parameterTypes ')']
+ *
e.g.
+ * - java.lang.Object()
+ * - Main(*)
+ * - <Exception>Sample(Exception)
+ *
+ * Type arguments have the same pattern that for type patterns
+ * @see #createTypePattern(String,int,int,char)
+ */
+private static SearchPattern createMethodOrConstructorPattern(String patternString, int limitTo, int matchRule, boolean isConstructor, boolean isFunction) {
+
+ Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+ scanner.setSource(patternString.toCharArray());
+ final int InsideSelector = 1;
+ final int InsideTypeArguments = 2;
+ final int InsideParameter = 3;
+ final int InsideReturnType = 4;
+ int lastToken = -1;
+
+ String declaringType = null, selector = null, parameterType = null;
+ String[] parameterTypes = null;
+ char[][] typeArguments = null;
+ String typeArgumentsString = null;
+ int parameterCount = -1;
+ String returnType = null;
+ boolean foundClosingParenthesis = false;
+ int mode = InsideSelector;
+ int token, argCount = 0;
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ while (token != TerminalTokens.TokenNameEOF) {
+ switch(mode) {
+ // read declaring type and selector
+ case InsideSelector :
+ if (argCount == 0) {
+ switch (token) {
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ if (selector == null || lastToken == TerminalTokens.TokenNameDOT) {
+ if (typeArgumentsString != null) return null; // invalid syntax
+ typeArgumentsString = scanner.getCurrentTokenString();
+ mode = InsideTypeArguments;
+ break;
+ }
+ if (declaringType == null) {
+ declaringType = selector;
+ } else {
+ declaringType += '.' + selector;
+ }
+ declaringType += scanner.getCurrentTokenString();
+ selector = null;
+ break;
+ case TerminalTokens.TokenNameDOT:
+ if (typeArgumentsString != null) return null; // invalid syntax
+ if (declaringType == null) {
+ if (selector == null) return null; // invalid syntax
+ declaringType = selector;
+ } else if (selector != null) {
+ declaringType += scanner.getCurrentTokenString() + selector;
+ }
+ selector = null;
+ break;
+ case TerminalTokens.TokenNameLPAREN:
+ parameterTypes = new String[5];
+ parameterCount = 0;
+ mode = InsideParameter;
+ break;
+ case TerminalTokens.TokenNameWHITESPACE:
+ switch (lastToken) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ case TerminalTokens.TokenNameDOT:
+ case TerminalTokens.TokenNameGREATER:
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ break;
+ default:
+ mode = InsideReturnType;
+ break;
+ }
+ break;
+ default: // all other tokens are considered identifiers (see bug 21763 Problem in JavaScript search [search])
+ if (selector == null)
+ selector = scanner.getCurrentTokenString();
+ else
+ selector += scanner.getCurrentTokenString();
+ break;
+ }
+ } else {
+ if (declaringType == null) return null; // invalid syntax
+ switch (token) {
+ case TerminalTokens.TokenNameGREATER:
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ argCount--;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ break;
+ }
+ declaringType += scanner.getCurrentTokenString();
+ }
+ break;
+ // read type arguments
+ case InsideTypeArguments:
+ if (typeArgumentsString == null) return null; // invalid syntax
+ typeArgumentsString += scanner.getCurrentTokenString();
+ switch (token) {
+ case TerminalTokens.TokenNameGREATER:
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ argCount--;
+ if (argCount == 0) {
+ typeArguments = new char[0][0];
+ mode = InsideSelector;
+ }
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ break;
+ }
+ break;
+ // read parameter types
+ case InsideParameter :
+ if (argCount == 0) {
+ switch (token) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ break;
+ case TerminalTokens.TokenNameCOMMA:
+ if (parameterType == null) return null;
+ if (parameterTypes != null) {
+ if (parameterTypes.length == parameterCount)
+ System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
+ parameterTypes[parameterCount++] = parameterType;
+ }
+ parameterType = null;
+ break;
+ case TerminalTokens.TokenNameRPAREN:
+ foundClosingParenthesis = true;
+ if (parameterType != null && parameterTypes != null) {
+ if (parameterTypes.length == parameterCount)
+ System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
+ parameterTypes[parameterCount++] = parameterType;
+ }
+ mode = isConstructor ? InsideTypeArguments : InsideReturnType;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ if (parameterType == null) return null; // invalid syntax
+ // fall through next case to add token
+ default: // all other tokens are considered identifiers (see bug 21763 Problem in JavaScript search [search])
+ if (parameterType == null)
+ parameterType = scanner.getCurrentTokenString();
+ else
+ parameterType += scanner.getCurrentTokenString();
+ }
+ } else {
+ if (parameterType == null) return null; // invalid syntax
+ switch (token) {
+ case TerminalTokens.TokenNameGREATER:
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ argCount--;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ break;
+ }
+ parameterType += scanner.getCurrentTokenString();
+ }
+ break;
+ // read return type
+ case InsideReturnType:
+ if (argCount == 0) {
+ switch (token) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ break;
+ case TerminalTokens.TokenNameLPAREN:
+ parameterTypes = new String[5];
+ parameterCount = 0;
+ mode = InsideParameter;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ if (returnType == null) return null; // invalid syntax
+ // fall through next case to add token
+ default: // all other tokens are considered identifiers (see bug 21763 Problem in JavaScript search [search])
+ if (returnType == null)
+ returnType = scanner.getCurrentTokenString();
+ else
+ returnType += scanner.getCurrentTokenString();
+ }
+ } else {
+ if (returnType == null) return null; // invalid syntax
+ switch (token) {
+ case TerminalTokens.TokenNameGREATER:
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ argCount--;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ break;
+ }
+ returnType += scanner.getCurrentTokenString();
+ }
+ break;
+ }
+ lastToken = token;
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ }
+ // parenthesis mismatch
+ if (parameterCount>0 && !foundClosingParenthesis) return null;
+ // type arguments mismatch
+ if (argCount > 0) return null;
+
+ char[] selectorChars = null;
+ if (isConstructor) {
+ // retrieve type for constructor patterns
+ if (declaringType == null)
+ declaringType = selector;
+ else if (selector != null)
+ declaringType += '.' + selector;
+ } else {
+ // get selector chars
+ if (selector == null) return null;
+ selectorChars = selector.toCharArray();
+ if (selectorChars.length == 1 && selectorChars[0] == '*')
+ selectorChars = null;
+ }
+
+ char[] declaringTypeQualification = null, declaringTypeSimpleName = null;
+ char[] returnTypeQualification = null, returnTypeSimpleName = null;
+ char[][] parameterTypeQualifications = null, parameterTypeSimpleNames = null;
+ // Signatures
+ String declaringTypeSignature = null;
+ String returnTypeSignature = null;
+ String[] parameterTypeSignatures = null;
+
+ // extract declaring type infos
+ if (declaringType != null) {
+ // get declaring type part and signature
+ char[] declaringTypePart = null;
+ try {
+ declaringTypeSignature = Signature.createTypeSignature(declaringType, false);
+ declaringTypePart = declaringType.toCharArray();
+ }
+ catch (IllegalArgumentException iae) {
+ // declaring type is invalid
+ return null;
+ }
+ int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart);
+ if (lastDotPosition >= 0) {
+ declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition);
+ if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*')
+ declaringTypeQualification = null;
+ declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length);
+ } else {
+ declaringTypeSimpleName = declaringTypePart;
+ }
+ if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*')
+ declaringTypeSimpleName = null;
+ }
+ // extract parameter types infos
+ if (parameterCount >= 0) {
+ parameterTypeQualifications = new char[parameterCount][];
+ parameterTypeSimpleNames = new char[parameterCount][];
+ parameterTypeSignatures = new String[parameterCount];
+ for (int i = 0; i < parameterCount; i++) {
+ // get parameter type part and signature
+ char[] parameterTypePart = null;
+ try {
+ if (parameterTypes != null) {
+ parameterTypeSignatures[i] = Signature.createTypeSignature(parameterTypes[i], false);
+ parameterTypePart = parameterTypes[i].toCharArray();
+ }
+ }
+ catch (IllegalArgumentException iae) {
+ // string is not a valid type syntax
+ return null;
+ }
+ int lastDotPosition = parameterTypePart==null ? -1 : CharOperation.lastIndexOf('.', parameterTypePart);
+ if (parameterTypePart != null && lastDotPosition >= 0) {
+ parameterTypeQualifications[i] = CharOperation.subarray(parameterTypePart, 0, lastDotPosition);
+ if (parameterTypeQualifications[i].length == 1 && parameterTypeQualifications[i][0] == '*') {
+ parameterTypeQualifications[i] = null;
+ } else {
+ // prefix with a '*' as the full qualification could be bigger (because of an import)
+ parameterTypeQualifications[i] = CharOperation.concat(IIndexConstants.ONE_STAR, parameterTypeQualifications[i]);
+ }
+ parameterTypeSimpleNames[i] = CharOperation.subarray(parameterTypePart, lastDotPosition+1, parameterTypePart.length);
+ } else {
+ parameterTypeQualifications[i] = null;
+ parameterTypeSimpleNames[i] = parameterTypePart;
+ }
+ if (parameterTypeSimpleNames[i].length == 1 && parameterTypeSimpleNames[i][0] == '*')
+ parameterTypeSimpleNames[i] = null;
+ }
+ }
+ // extract return type infos
+ if (returnType != null) {
+ // get return type part and signature
+ char[] returnTypePart = null;
+ try {
+ returnTypeSignature = Signature.createTypeSignature(returnType, false);
+ returnTypePart = returnType.toCharArray();
+ }
+ catch (IllegalArgumentException iae) {
+ // declaring type is invalid
+ return null;
+ }
+ int lastDotPosition = CharOperation.lastIndexOf('.', returnTypePart);
+ if (lastDotPosition >= 0) {
+ returnTypeQualification = CharOperation.subarray(returnTypePart, 0, lastDotPosition);
+ if (returnTypeQualification.length == 1 && returnTypeQualification[0] == '*') {
+ returnTypeQualification = null;
+ } else {
+ // because of an import
+ returnTypeQualification = CharOperation.concat(IIndexConstants.ONE_STAR, returnTypeQualification);
+ }
+ returnTypeSimpleName = CharOperation.subarray(returnTypePart, lastDotPosition+1, returnTypePart.length);
+ } else {
+ returnTypeSimpleName = returnTypePart;
+ }
+ if (returnTypeSimpleName.length == 1 && returnTypeSimpleName[0] == '*')
+ returnTypeSimpleName = null;
+ }
+ // Create method/constructor pattern
+ boolean findDeclarations = true;
+ boolean findReferences = true;
+ switch (limitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ findReferences = false;
+ break;
+ case IJavaScriptSearchConstants.REFERENCES :
+ findDeclarations = false;
+ break;
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ break;
+ }
+ if (isConstructor) {
+ return new ConstructorPattern(
+ findDeclarations,
+ findReferences,
+ declaringTypeSimpleName,
+ declaringTypeQualification,
+ declaringTypeSignature,
+ parameterTypeQualifications,
+ parameterTypeSimpleNames,
+ parameterTypeSignatures,
+ typeArguments,
+ matchRule);
+ } else {
+ return new MethodPattern(
+ findDeclarations,
+ findReferences,
+ isFunction,
+ selectorChars,
+ declaringTypeQualification,
+ declaringTypeSimpleName,
+ declaringTypeSignature,
+ returnTypeQualification,
+ returnTypeSimpleName,
+ returnTypeSignature,
+ parameterTypeQualifications,
+ parameterTypeSimpleNames,
+ parameterTypeSignatures,
+ typeArguments,
+ matchRule);
+ }
+}
+
+/**
+ * Returns a search pattern that combines the given two patterns into an
+ * "or" pattern. The search result will match either the left pattern or the
+ * right pattern.
+ *
+ * @param leftPattern the left pattern
+ * @param rightPattern the right pattern
+ * @return an "or" pattern
+ */
+public static SearchPattern createOrPattern(SearchPattern leftPattern, SearchPattern rightPattern) {
+ return new OrPattern(leftPattern, rightPattern);
+}
+
+private static SearchPattern createPackagePattern(String patternString, int limitTo, int matchRule) {
+ switch (limitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ return new PackageDeclarationPattern(patternString.toCharArray(), matchRule);
+ case IJavaScriptSearchConstants.REFERENCES :
+ return new PackageReferencePattern(patternString.toCharArray(), matchRule);
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ return new OrPattern(
+ new PackageDeclarationPattern(patternString.toCharArray(), matchRule),
+ new PackageReferencePattern(patternString.toCharArray(), matchRule)
+ );
+ }
+ return null;
+}
+
+/**
+ * Returns a search pattern based on a given string pattern. The string patterns support '*' wild-cards.
+ * The remaining parameters are used to narrow down the type of expected results.
+ *
+ *
+ * Examples:
+ *
+ * - search for case insensitive references to
Object
:
+ * createSearchPattern("Object", TYPE, REFERENCES, false);
+ * - search for case sensitive references to exact
Object()
constructor:
+ * createSearchPattern("java.lang.Object()", CONSTRUCTOR, REFERENCES, true);
+ * - search for implementers of
java.lang.Runnable
:
+ * createSearchPattern("java.lang.Runnable", TYPE, IMPLEMENTORS, true);
+ *
+ * @param stringPattern the given pattern
+ * @param searchFor determines the nature of the searched elements
+ *
+ * - {@link IJavaScriptSearchConstants#CLASS}: only look for classes
+ * - {@link IJavaScriptSearchConstants#INTERFACE}: only look for interfaces
+ * - {@link IJavaScriptSearchConstants#ENUM}: only look for enumeration
+ * - {@link IJavaScriptSearchConstants#ANNOTATION_TYPE}: only look for annotation type
+ * - {@link IJavaScriptSearchConstants#CLASS_AND_ENUM}: only look for classes and enumerations
+ * - {@link IJavaScriptSearchConstants#CLASS_AND_INTERFACE}: only look for classes and interfaces
+ * - {@link IJavaScriptSearchConstants#TYPE}: look for all types (ie. classes, interfaces, enum and annotation types)
+ * - {@link IJavaScriptSearchConstants#FIELD}: look for fields
+ * - {@link IJavaScriptSearchConstants#METHOD}: look for methods
+ * - {@link IJavaScriptSearchConstants#CONSTRUCTOR}: look for constructors
+ * - {@link IJavaScriptSearchConstants#PACKAGE}: look for packages
+ *
+ * @param limitTo determines the nature of the expected matches
+ *
+ * - {@link IJavaScriptSearchConstants#DECLARATIONS}: will search declarations matching
+ * with the corresponding element. In case the element is a method, declarations of matching
+ * methods in subtypes will also be found, allowing to find declarations of abstract methods, etc.
+ * Note that additional flags {@link IJavaScriptSearchConstants#IGNORE_DECLARING_TYPE} and
+ * {@link IJavaScriptSearchConstants#IGNORE_RETURN_TYPE} are ignored for string patterns.
+ * This is due to the fact that client may omit to define them in string pattern to have same behavior.
+ *
+ * - {@link IJavaScriptSearchConstants#REFERENCES}: will search references to the given element.
+ * - {@link IJavaScriptSearchConstants#ALL_OCCURRENCES}: will search for either declarations or
+ * references as specified above.
+ *
+ * - {@link IJavaScriptSearchConstants#IMPLEMENTORS}: for types, will find all types
+ * which directly implement/extend a given interface.
+ * Note that types may be only classes or only interfaces if {@link IJavaScriptSearchConstants#CLASS } or
+ * {@link IJavaScriptSearchConstants#INTERFACE} is respectively used instead of {@link IJavaScriptSearchConstants#TYPE}.
+ *
+ *
+ * @param matchRule one of {@link #R_EXACT_MATCH}, {@link #R_PREFIX_MATCH}, {@link #R_PATTERN_MATCH},
+ * {@link #R_REGEXP_MATCH}, {@link #R_CAMELCASE_MATCH} combined with one of following values:
+ * {@link #R_CASE_SENSITIVE}, {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH}.
+ * e.g. {@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * {@link #R_PREFIX_MATCH} if a prefix non case sensitive match is requested or {@link #R_EXACT_MATCH} | {@link #R_ERASURE_MATCH}
+ * if a non case sensitive and erasure match is requested.
+ * Note that {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH} have no effect
+ * on non-generic types/methods search.
+ * Note also that default behavior for generic types/methods search is to find exact matches.
+ * @return a search pattern on the given string pattern, or null
if the string pattern is ill-formed
+ */
+public static SearchPattern createPattern(String stringPattern, int searchFor, int limitTo, int matchRule) {
+ if (stringPattern == null || stringPattern.length() == 0) return null;
+
+ if ((matchRule = validateMatchRule(stringPattern, matchRule)) == -1) {
+ return null;
+ }
+
+ // Ignore additional nature flags
+ limitTo &= ~(IJavaScriptSearchConstants.IGNORE_DECLARING_TYPE+IJavaScriptSearchConstants.IGNORE_RETURN_TYPE);
+
+ switch (searchFor) {
+ case IJavaScriptSearchConstants.CLASS:
+ return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.CLASS_SUFFIX);
+ case IJavaScriptSearchConstants.TYPE:
+ return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.TYPE_SUFFIX);
+ case IJavaScriptSearchConstants.FUNCTION:
+ return createMethodOrConstructorPattern(stringPattern, limitTo, matchRule, false/*not a constructor*/,true);
+ case IJavaScriptSearchConstants.METHOD:
+ return createMethodOrConstructorPattern(stringPattern, limitTo, matchRule, false/*not a constructor*/,false);
+ case IJavaScriptSearchConstants.CONSTRUCTOR:
+ return createMethodOrConstructorPattern(stringPattern, limitTo, matchRule, true/*constructor*/,false);
+ case IJavaScriptSearchConstants.FIELD:
+ return createFieldPattern(stringPattern, limitTo, matchRule,false);
+ case IJavaScriptSearchConstants.VAR:
+ return createFieldPattern(stringPattern, limitTo, matchRule,true);
+ case IJavaScriptSearchConstants.PACKAGE:
+ return createPackagePattern(stringPattern, limitTo, matchRule);
+ }
+ return null;
+}
+
+/**
+ * Returns a search pattern based on a given JavaScript element.
+ * The pattern is used to trigger the appropriate search.
+ *
+ * Note that for generic searches, the returned pattern consider {@link #R_ERASURE_MATCH} matches.
+ * If other kind of generic matches (ie. {@link #R_EXACT_MATCH} or {@link #R_EQUIVALENT_MATCH})
+ * are expected, {@link #createPattern(IJavaScriptElement, int, int)} method need to be used instead with
+ * the explicit match rule specified.
+ *
+ * The pattern can be parameterized as follows:
+ *
+ * @param element the JavaScript element the search pattern is based on
+ * @param limitTo determines the nature of the expected matches
+ *
+ * - {@link IJavaScriptSearchConstants#DECLARATIONS}: will search declarations matching
+ * with the corresponding element. In case the element is a method, declarations of matching
+ * methods in subtypes will also be found, allowing to find declarations of abstract methods, etc.
+ * Some additional flags may be specified while searching declaration:
+ *
+ * - {@link IJavaScriptSearchConstants#IGNORE_DECLARING_TYPE}: declaring type will be ignored
+ * during the search.
+ * For example using following test case:
+ *
+ * class A { A method() { return null; } }
+ * class B extends A { B method() { return null; } }
+ * class C { A method() { return null; } }
+ *
+ * search for method
declaration with this flag
+ * will return 2 matches: in A and in C
+ *
+ * - {@link IJavaScriptSearchConstants#IGNORE_RETURN_TYPE}: return type will be ignored
+ * during the search.
+ * Using same example, search for method
declaration with this flag
+ * will return 2 matches: in A and in B.
+ *
+ *
+ * Note that these two flags may be combined and both declaring and return types can be ignored
+ * during the search. Then, using same example, search for method
declaration
+ * with these 2 flags will return 3 matches: in A, in B and in C
+ *
+ * - {@link IJavaScriptSearchConstants#REFERENCES}: will search references to the given element.
+ * - {@link IJavaScriptSearchConstants#ALL_OCCURRENCES}: will search for either declarations or
+ * references as specified above.
+ *
+ * - {@link IJavaScriptSearchConstants#IMPLEMENTORS}: for types, will find all types
+ * which directly implement/extend a given interface.
+ *
+ *
+ * @return a search pattern for a JavaScript element or null
if the given element is ill-formed
+ */
+public static SearchPattern createPattern(IJavaScriptElement element, int limitTo) {
+ return createPattern(element, limitTo, R_EXACT_MATCH | R_CASE_SENSITIVE | R_ERASURE_MATCH);
+}
+
+/**
+ * Returns a search pattern based on a given JavaScript element.
+ * The pattern is used to trigger the appropriate search, and can be parameterized as follows:
+ *
+ * @param element the JavaScript element the search pattern is based on
+ * @param limitTo determines the nature of the expected matches
+ *
+ * - {@link IJavaScriptSearchConstants#DECLARATIONS}: will search declarations matching
+ * with the corresponding element. In case the element is a method, declarations of matching
+ * methods in subtypes will also be found, allowing to find declarations of abstract methods, etc.
+ * Some additional flags may be specified while searching declaration:
+ *
+ * - {@link IJavaScriptSearchConstants#IGNORE_DECLARING_TYPE}: declaring type will be ignored
+ * during the search.
+ * For example using following test case:
+ *
+ * class A { A method() { return null; } }
+ * class B extends A { B method() { return null; } }
+ * class C { A method() { return null; } }
+ *
+ * search for method
declaration with this flag
+ * will return 2 matches: in A and in C
+ *
+ * - {@link IJavaScriptSearchConstants#IGNORE_RETURN_TYPE}: return type will be ignored
+ * during the search.
+ * Using same example, search for method
declaration with this flag
+ * will return 2 matches: in A and in B.
+ *
+ *
+ * Note that these two flags may be combined and both declaring and return types can be ignored
+ * during the search. Then, using same example, search for method
declaration
+ * with these 2 flags will return 3 matches: in A, in B and in C
+ *
+ * - {@link IJavaScriptSearchConstants#REFERENCES}: will search references to the given element.
+ * - {@link IJavaScriptSearchConstants#ALL_OCCURRENCES}: will search for either declarations or
+ * references as specified above.
+ *
+ * - {@link IJavaScriptSearchConstants#IMPLEMENTORS}: for types, will find all types
+ * which directly implement/extend a given interface.
+ *
+ *
+ * @param matchRule one of {@link #R_EXACT_MATCH}, {@link #R_PREFIX_MATCH}, {@link #R_PATTERN_MATCH},
+ * {@link #R_REGEXP_MATCH}, {@link #R_CAMELCASE_MATCH} combined with one of following values:
+ * {@link #R_CASE_SENSITIVE}, {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH}.
+ * e.g. {@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE} if an exact and case sensitive match is requested,
+ * {@link #R_PREFIX_MATCH} if a prefix non case sensitive match is requested or {@link #R_EXACT_MATCH} |{@link #R_ERASURE_MATCH}
+ * if a non case sensitive and erasure match is requested.
+ * Note that {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH} have no effect on non-generic types
+ * or methods search.
+ * Note also that default behavior for generic types or methods is to find exact matches.
+ * @return a search pattern for a JavaScript element or null
if the given element is ill-formed
+ *
+ */
+public static SearchPattern createPattern(IJavaScriptElement element, int limitTo, int matchRule) {
+ SearchPattern searchPattern = null;
+ int lastDot;
+ boolean ignoreDeclaringType = false;
+ boolean ignoreReturnType = false;
+ int maskedLimitTo = limitTo & ~(IJavaScriptSearchConstants.IGNORE_DECLARING_TYPE+IJavaScriptSearchConstants.IGNORE_RETURN_TYPE);
+ if (maskedLimitTo == IJavaScriptSearchConstants.DECLARATIONS || maskedLimitTo == IJavaScriptSearchConstants.ALL_OCCURRENCES) {
+ ignoreDeclaringType = (limitTo & IJavaScriptSearchConstants.IGNORE_DECLARING_TYPE) != 0;
+ ignoreReturnType = (limitTo & IJavaScriptSearchConstants.IGNORE_RETURN_TYPE) != 0;
+ }
+ char[] declaringSimpleName = null;
+ char[] declaringQualification = null;
+ boolean isVar=false;
+ boolean isFunction=false;
+ switch (element.getElementType()) {
+ case IJavaScriptElement.FIELD :
+ IField field = (IField) element;
+ IType declaringClassForField = field.getDeclaringType();
+ isVar=(declaringClassForField==null);
+ if (!ignoreDeclaringType) {
+ if (declaringClassForField!=null)
+ {
+ declaringSimpleName = declaringClassForField.getElementName().toCharArray();
+ declaringQualification = declaringClassForField.getPackageFragment().getElementName().toCharArray();
+ char[][] enclosingNames = enclosingTypeNames(declaringClassForField);
+ if (enclosingNames.length > 0) {
+ declaringQualification = CharOperation.concat(declaringQualification, CharOperation.concatWith(enclosingNames, '.'), '.');
+ }
+ }
+ }
+ char[] name = field.getElementName().toCharArray();
+ char[] typeSimpleName = null;
+ char[] typeQualification = null;
+ String typeSignature = null;
+ if (!ignoreReturnType) {
+ try {
+ typeSignature = field.getTypeSignature();
+ char[] signature = typeSignature.toCharArray();
+ char[] typeErasure = Signature.toCharArray(signature);
+ CharOperation.replace(typeErasure, '$', '.');
+ if ((lastDot = CharOperation.lastIndexOf('.', typeErasure)) == -1) {
+ typeSimpleName = typeErasure;
+ } else {
+ typeSimpleName = CharOperation.subarray(typeErasure, lastDot + 1, typeErasure.length);
+ typeQualification = CharOperation.subarray(typeErasure, 0, lastDot);
+ if (!field.isBinary()) {
+ // prefix with a '*' as the full qualification could be bigger (because of an import)
+ typeQualification = CharOperation.concat(IIndexConstants.ONE_STAR, typeQualification);
+ }
+ }
+ } catch (JavaScriptModelException e) {
+ return null;
+ }
+ }
+
+ // Create field pattern
+ boolean findDeclarations = false;
+ boolean readAccess = false;
+ boolean writeAccess = false;
+ switch (maskedLimitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ findDeclarations = true;
+ break;
+ case IJavaScriptSearchConstants.REFERENCES :
+ readAccess = true;
+ writeAccess = true;
+ break;
+ case IJavaScriptSearchConstants.READ_ACCESSES :
+ readAccess = true;
+ break;
+ case IJavaScriptSearchConstants.WRITE_ACCESSES :
+ writeAccess = true;
+ break;
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ findDeclarations = true;
+ readAccess = true;
+ writeAccess = true;
+ break;
+ }
+ searchPattern =
+ new FieldPattern(
+ findDeclarations,
+ readAccess,
+ writeAccess,
+ isVar,
+ name,
+ declaringQualification,
+ declaringSimpleName,
+ typeQualification,
+ typeSimpleName,
+ typeSignature,
+ matchRule,field);
+ break;
+ case IJavaScriptElement.IMPORT_DECLARATION :
+ String elementName = element.getElementName();
+ lastDot = elementName.lastIndexOf('.');
+ if (lastDot == -1) return null; // invalid import declaration
+ IImportDeclaration importDecl = (IImportDeclaration)element;
+ if (importDecl.isOnDemand()) {
+ searchPattern = createPackagePattern(elementName.substring(0, lastDot), maskedLimitTo, matchRule);
+ } else {
+ searchPattern =
+ createTypePattern(
+ elementName.substring(lastDot+1).toCharArray(),
+ elementName.substring(0, lastDot).toCharArray(),
+ null,
+ null,
+ null,
+ maskedLimitTo,
+ matchRule);
+ }
+ break;
+ case IJavaScriptElement.LOCAL_VARIABLE :
+ LocalVariable localVar = (LocalVariable) element;
+ boolean findVarDeclarations = false;
+ boolean findVarReadAccess = false;
+ boolean findVarWriteAccess = false;
+ switch (maskedLimitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ findVarDeclarations = true;
+ break;
+ case IJavaScriptSearchConstants.REFERENCES :
+ findVarReadAccess = true;
+ findVarWriteAccess = true;
+ break;
+ case IJavaScriptSearchConstants.READ_ACCESSES :
+ findVarReadAccess = true;
+ break;
+ case IJavaScriptSearchConstants.WRITE_ACCESSES :
+ findVarWriteAccess = true;
+ break;
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ findVarDeclarations = true;
+ findVarReadAccess = true;
+ findVarWriteAccess = true;
+ break;
+ }
+ searchPattern =
+ new LocalVariablePattern(
+ findVarDeclarations,
+ findVarReadAccess,
+ findVarWriteAccess,
+ localVar,
+ matchRule);
+ break;
+ case IJavaScriptElement.METHOD :
+ IFunction method = (IFunction) element;
+ boolean isConstructor;
+ try {
+ isConstructor = method.isConstructor();
+ } catch (JavaScriptModelException e) {
+ return null;
+ }
+ IType declaringClass = method.getDeclaringType();
+
+ if (declaringClass!=null) {
+ if (ignoreDeclaringType) {
+ if (isConstructor)
+ declaringSimpleName = declaringClass.getElementName()
+ .toCharArray();
+ } else {
+ declaringSimpleName = declaringClass.getElementName()
+ .toCharArray();
+ declaringQualification = declaringClass
+ .getPackageFragment().getElementName()
+ .toCharArray();
+ char[][] enclosingNames = enclosingTypeNames(declaringClass);
+ if (enclosingNames.length > 0) {
+ declaringQualification = CharOperation.concat(
+ declaringQualification, CharOperation
+ .concatWith(enclosingNames, '.'), '.');
+ }
+ }
+ }
+ else
+ isFunction=true;
+ char[] selector = method.getElementName().toCharArray();
+ char[] returnSimpleName = null;
+ char[] returnQualification = null;
+ String returnSignature = null;
+ if (!ignoreReturnType) {
+ try {
+ returnSignature = method.getReturnType();
+ char[] signature = returnSignature.toCharArray();
+ char[] returnErasure = Signature.toCharArray(signature);
+ CharOperation.replace(returnErasure, '$', '.');
+ if ((lastDot = CharOperation.lastIndexOf('.', returnErasure)) == -1) {
+ returnSimpleName = returnErasure;
+ } else {
+ returnSimpleName = CharOperation.subarray(returnErasure, lastDot + 1, returnErasure.length);
+ returnQualification = CharOperation.subarray(returnErasure, 0, lastDot);
+ if (!method.isBinary()) {
+ // prefix with a '*' as the full qualification could be bigger (because of an import)
+ CharOperation.concat(IIndexConstants.ONE_STAR, returnQualification);
+ }
+ }
+ } catch (JavaScriptModelException e) {
+ return null;
+ }
+ }
+ String[] parameterTypes = method.getParameterTypes();
+ int paramCount = parameterTypes.length;
+ char[][] parameterSimpleNames = new char[paramCount][];
+ char[][] parameterQualifications = new char[paramCount][];
+ String[] parameterSignatures = new String[paramCount];
+ for (int i = 0; i < paramCount; i++) {
+ parameterSignatures[i] = parameterTypes[i];
+ char[] signature = parameterSignatures[i].toCharArray();
+ char[] paramErasure = Signature.toCharArray(signature);
+ CharOperation.replace(paramErasure, '$', '.');
+ if ((lastDot = CharOperation.lastIndexOf('.', paramErasure)) == -1) {
+ parameterSimpleNames[i] = paramErasure;
+ parameterQualifications[i] = null;
+ } else {
+ parameterSimpleNames[i] = CharOperation.subarray(paramErasure, lastDot + 1, paramErasure.length);
+ parameterQualifications[i] = CharOperation.subarray(paramErasure, 0, lastDot);
+ if (!method.isBinary()) {
+ // prefix with a '*' as the full qualification could be bigger (because of an import)
+ CharOperation.concat(IIndexConstants.ONE_STAR, parameterQualifications[i]);
+ }
+ }
+ }
+
+ // Create method/constructor pattern
+ boolean findMethodDeclarations = true;
+ boolean findMethodReferences = true;
+ switch (maskedLimitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ findMethodReferences = false;
+ break;
+ case IJavaScriptSearchConstants.REFERENCES :
+ findMethodDeclarations = false;
+ break;
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ break;
+ }
+ if (isConstructor) {
+ searchPattern =
+ new ConstructorPattern(
+ findMethodDeclarations,
+ findMethodReferences,
+ declaringSimpleName,
+ declaringQualification,
+ parameterQualifications,
+ parameterSimpleNames,
+ parameterSignatures,
+ method,
+ matchRule);
+ } else {
+ searchPattern =
+ new MethodPattern(
+ findMethodDeclarations,
+ findMethodReferences,
+ isFunction,
+ selector,
+ declaringQualification,
+ declaringSimpleName,
+ returnQualification,
+ returnSimpleName,
+ returnSignature,
+ parameterQualifications,
+ parameterSimpleNames,
+ parameterSignatures,
+ method,
+ matchRule);
+ }
+ break;
+ case IJavaScriptElement.TYPE :
+ IType type = (IType)element;
+ searchPattern = createTypePattern(
+ type.getElementName().toCharArray(),
+ type.getPackageFragment().getElementName().toCharArray(),
+ ignoreDeclaringType ? null : enclosingTypeNames(type),
+ null,
+ type,
+ maskedLimitTo,
+ matchRule);
+ break;
+ case IJavaScriptElement.PACKAGE_FRAGMENT :
+ searchPattern = createPackagePattern(element.getElementName(), maskedLimitTo, matchRule);
+ break;
+ }
+ if (searchPattern != null)
+ MatchLocator.setFocus(searchPattern, element);
+ return searchPattern;
+}
+
+private static SearchPattern createTypePattern(char[] simpleName, char[] packageName, char[][] enclosingTypeNames, String typeSignature, IType type, int limitTo, int matchRule) {
+ switch (limitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS :
+ return new TypeDeclarationPattern(
+ packageName,
+ enclosingTypeNames,
+ simpleName,
+ IIndexConstants.TYPE_SUFFIX,
+ matchRule);
+ case IJavaScriptSearchConstants.REFERENCES :
+ if (type != null) {
+ return new TypeReferencePattern(
+ CharOperation.concatWith(packageName, enclosingTypeNames, '.'),
+ simpleName,
+ type,
+ matchRule);
+ }
+ return new TypeReferencePattern(
+ CharOperation.concatWith(packageName, enclosingTypeNames, '.'),
+ simpleName,
+ typeSignature,
+ matchRule);
+ case IJavaScriptSearchConstants.IMPLEMENTORS :
+ return new SuperTypeReferencePattern(
+ CharOperation.concatWith(packageName, enclosingTypeNames, '.'),
+ simpleName,
+ matchRule);
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ return new OrPattern(
+ new TypeDeclarationPattern(
+ packageName,
+ enclosingTypeNames,
+ simpleName,
+ IIndexConstants.TYPE_SUFFIX,
+ matchRule),
+ (type != null)
+ ? new TypeReferencePattern(
+ CharOperation.concatWith(packageName, enclosingTypeNames, '.'),
+ simpleName,
+ type,
+ matchRule)
+ : new TypeReferencePattern(
+ CharOperation.concatWith(packageName, enclosingTypeNames, '.'),
+ simpleName,
+ typeSignature,
+ matchRule)
+ );
+ }
+ return null;
+}
+/**
+ * Type pattern are formed by [qualification '.']type [typeArguments].
+ * e.g. java.lang.Object
+ * Runnable
+ * List<String>
+ */
+private static SearchPattern createTypePattern(String patternString, int limitTo, int matchRule, char indexSuffix) {
+
+ Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+ scanner.setSource(patternString.toCharArray());
+ String type = null;
+ int token;
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ int argCount = 0;
+ while (token != TerminalTokens.TokenNameEOF) {
+ if (argCount == 0) {
+ switch (token) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ // fall through default case to add token to type
+ default: // all other tokens are considered identifiers (see bug 21763 Problem in JavaScript search [search])
+ if (type == null)
+ type = scanner.getCurrentTokenString();
+ else
+ type += scanner.getCurrentTokenString();
+ }
+ } else {
+ switch (token) {
+ case TerminalTokens.TokenNameGREATER:
+ case TerminalTokens.TokenNameRIGHT_SHIFT:
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
+ argCount--;
+ break;
+ case TerminalTokens.TokenNameLESS:
+ argCount++;
+ break;
+ }
+ if (type == null) return null; // invalid syntax
+ type += scanner.getCurrentTokenString();
+ }
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return null;
+ }
+ }
+ if (type == null) return null;
+ String typeSignature = null;
+ char[] qualificationChars = null, typeChars = null;
+
+ // get type part and signature
+ char[] typePart = null;
+ try {
+ typeSignature = Signature.createTypeSignature(type, false);
+ typePart = type.toCharArray();
+ }
+ catch (IllegalArgumentException iae) {
+ // string is not a valid type syntax
+ return null;
+ }
+
+ // get qualification name
+ int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
+ if (lastDotPosition >= 0) {
+ qualificationChars = CharOperation.subarray(typePart, 0, lastDotPosition);
+ if (qualificationChars.length == 1 && qualificationChars[0] == '*')
+ qualificationChars = null;
+ typeChars = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length);
+ } else {
+ typeChars = typePart;
+ }
+ if (typeChars.length == 1 && typeChars[0] == '*') {
+ typeChars = null;
+ }
+ switch (limitTo) {
+ case IJavaScriptSearchConstants.DECLARATIONS : // cannot search for explicit member types
+ return new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, indexSuffix, matchRule);
+ case IJavaScriptSearchConstants.REFERENCES :
+ return new TypeReferencePattern(qualificationChars, typeChars, typeSignature, matchRule);
+ case IJavaScriptSearchConstants.IMPLEMENTORS :
+ return new SuperTypeReferencePattern(qualificationChars, typeChars, matchRule);
+ case IJavaScriptSearchConstants.ALL_OCCURRENCES :
+ return new OrPattern(
+ new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, indexSuffix, matchRule),// cannot search for explicit member types
+ new TypeReferencePattern(qualificationChars, typeChars, matchRule));
+ }
+ return null;
+}
+/**
+ * Returns the enclosing type names of the given type.
+ */
+private static char[][] enclosingTypeNames(IType type) {
+ IJavaScriptElement parent = type.getParent();
+ switch (parent.getElementType()) {
+ case IJavaScriptElement.CLASS_FILE:
+ // For a binary type, the parent is not the enclosing type, but the declaring type is.
+ // (see bug 20532 Declaration of member binary type not found)
+ IType declaringType = type.getDeclaringType();
+ if (declaringType == null) return CharOperation.NO_CHAR_CHAR;
+ return CharOperation.arrayConcat(
+ enclosingTypeNames(declaringType),
+ declaringType.getElementName().toCharArray());
+ case IJavaScriptElement.JAVASCRIPT_UNIT:
+ return CharOperation.NO_CHAR_CHAR;
+ case IJavaScriptElement.FIELD:
+ case IJavaScriptElement.INITIALIZER:
+ case IJavaScriptElement.METHOD:
+ IType declaringClass = ((IMember) parent).getDeclaringType();
+ if (declaringClass!=null)
+ return CharOperation.arrayConcat(
+ enclosingTypeNames(declaringClass),
+ new char[][] {declaringClass.getElementName().toCharArray(), IIndexConstants.ONE_STAR});
+ else
+ return CharOperation.NO_CHAR_CHAR;
+ case IJavaScriptElement.TYPE:
+ return CharOperation.arrayConcat(
+ enclosingTypeNames((IType)parent),
+ parent.getElementName().toCharArray());
+ default:
+ return null;
+ }
+}
+
+/**
+ * Decode the given index key in this pattern. The decoded index key is used by
+ * {@link #matchesDecodedKey(SearchPattern)} to find out if the corresponding index entry
+ * should be considered.
+ *
+ * This method should be re-implemented in subclasses that need to decode an index key.
+ *
+ *
+ * @param key the given index key
+ */
+public void decodeIndexKey(char[] key) {
+ // called from findIndexMatches(), override as necessary
+}
+/**
+ * Returns a blank pattern that can be used as a record to decode an index key.
+ *
+ * Implementors of this method should return a new search pattern that is going to be used
+ * to decode index keys.
+ *
+ *
+ * @return a new blank pattern
+ * @see #decodeIndexKey(char[])
+ */
+public abstract SearchPattern getBlankPattern();
+/**
+ * Returns a key to find in relevant index categories, if null then all index entries are matched.
+ * The key will be matched according to some match rule. These potential matches
+ * will be further narrowed by the match locator, but precise match locating can be expensive,
+ * and index query should be as accurate as possible so as to eliminate obvious false hits.
+ *
+ * This method should be re-implemented in subclasses that need to narrow down the
+ * index query.
+ *
+ *
+ * @return an index key from this pattern, or null
if all index entries are matched.
+ */
+public char[] getIndexKey() {
+ return null; // called from queryIn(), override as necessary
+}
+/**
+ * Returns an array of index categories to consider for this index query.
+ * These potential matches will be further narrowed by the match locator, but precise
+ * match locating can be expensive, and index query should be as accurate as possible
+ * so as to eliminate obvious false hits.
+ *
+ * This method should be re-implemented in subclasses that need to narrow down the
+ * index query.
+ *
+ *
+ * @return an array of index categories
+ */
+public char[][] getIndexCategories() {
+ return CharOperation.NO_CHAR_CHAR; // called from queryIn(), override as necessary
+}
+/**
+ * Returns the rule to apply for matching index keys. Can be exact match, prefix match, pattern match or regexp match.
+ * Rule can also be combined with a case sensitivity flag.
+ *
+ * @return one of R_EXACT_MATCH, R_PREFIX_MATCH, R_PATTERN_MATCH, R_REGEXP_MATCH combined with R_CASE_SENSITIVE,
+ * e.g. R_EXACT_MATCH | R_CASE_SENSITIVE if an exact and case sensitive match is requested,
+ * or R_PREFIX_MATCH if a prefix non case sensitive match is requested.
+ * [TODO (frederic) I hope R_ERASURE_MATCH doesn't need to be on this list. Because it would be a breaking API change.]
+ */
+public final int getMatchRule() {
+ return this.matchRule;
+}
+/**
+ * Returns whether this pattern matches the given pattern (representing a decoded index key).
+ *
+ * This method should be re-implemented in subclasses that need to narrow down the
+ * index query.
+ *
+ *
+ * @param decodedPattern a pattern representing a decoded index key
+ * @return whether this pattern matches the given pattern
+ */
+public boolean matchesDecodedKey(SearchPattern decodedPattern) {
+ return true; // called from findIndexMatches(), override as necessary if index key is encoded
+}
+
+/**
+ * Returns whether the given name matches the given pattern.
+ *
+ * This method should be re-implemented in subclasses that need to define how
+ * a name matches a pattern.
+ *
+ *
+ * @param pattern the given pattern, or null
to represent "*"
+ * @param name the given name
+ * @return whether the given name matches the given pattern
+ */
+public boolean matchesName(char[] pattern, char[] name) {
+ if (pattern == null) return true; // null is as if it was "*"
+ if (name != null) {
+ boolean isCaseSensitive = (this.matchRule & R_CASE_SENSITIVE) != 0;
+ boolean isCamelCase = (this.matchRule & R_CAMELCASE_MATCH) != 0;
+ int matchMode = this.matchRule & MODE_MASK;
+ boolean emptyPattern = pattern.length == 0;
+ if (matchMode == R_PREFIX_MATCH && emptyPattern) return true;
+ boolean sameLength = pattern.length == name.length;
+ boolean canBePrefix = name.length >= pattern.length;
+ boolean matchFirstChar = !isCaseSensitive || emptyPattern || (name.length > 0 && pattern[0] == name[0]);
+ if (isCamelCase && matchFirstChar && CharOperation.camelCaseMatch(pattern, name)) {
+ return true;
+ }
+ switch (matchMode) {
+ case R_EXACT_MATCH :
+ case R_FULL_MATCH :
+ if (!isCamelCase) {
+ if (sameLength && matchFirstChar) {
+ return CharOperation.equals(pattern, name, isCaseSensitive);
+ }
+ break;
+ }
+ // fall through next case to match as prefix if camel case failed
+ case R_PREFIX_MATCH :
+ if (canBePrefix && matchFirstChar) {
+ return CharOperation.prefixEquals(pattern, name, isCaseSensitive);
+ }
+ break;
+
+ case R_PATTERN_MATCH :
+ if (!isCaseSensitive)
+ pattern = CharOperation.toLowerCase(pattern);
+ return CharOperation.match(pattern, name, isCaseSensitive);
+
+ case R_REGEXP_MATCH :
+ // TODO (frederic) implement regular expression match
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Validate compatibility between given string pattern and match rule.
+ *
+ * Optimized (ie. returned match rule is modified) combinations are:
+ *
+ * - {@link #R_PATTERN_MATCH} without any '*' or '?' in string pattern:
+ * pattern match bit is unset,
+ *
+ * - {@link #R_PATTERN_MATCH} and {@link #R_PREFIX_MATCH} bits simultaneously set:
+ * prefix match bit is unset,
+ *
+ * - {@link #R_PATTERN_MATCH} and {@link #R_CAMELCASE_MATCH} bits simultaneously set:
+ * camel case match bit is unset,
+ *
+ * - {@link #R_CAMELCASE_MATCH} with invalid combination of uppercase and lowercase characters:
+ * camel case match bit is unset and replaced with prefix match pattern,
+ *
+ * - {@link #R_CAMELCASE_MATCH} combined with {@link #R_PREFIX_MATCH} and {@link #R_CASE_SENSITIVE}
+ * bits is reduced to only {@link #R_CAMELCASE_MATCH} as Camel Case search is already prefix and case sensitive,
+ *
+ *
+ *
+ * Rejected (ie. returned match rule -1) combinations are:
+ *
+ * - {@link #R_REGEXP_MATCH} with any other match mode bit set,
+ *
+ *
+ *
+ * @param stringPattern The string pattern
+ * @param matchRule The match rule
+ * @return Optimized valid match rule or -1 if an incompatibility was detected.
+ *
+ */
+public static int validateMatchRule(String stringPattern, int matchRule) {
+
+ // Verify Regexp match rule
+ if ((matchRule & R_REGEXP_MATCH) != 0) {
+ if ((matchRule & R_PATTERN_MATCH) != 0 || (matchRule & R_PREFIX_MATCH) != 0 || (matchRule & R_CAMELCASE_MATCH) != 0) {
+ return -1;
+ }
+ }
+
+ // Verify Pattern match rule
+ int starIndex = stringPattern.indexOf('*');
+ int questionIndex = stringPattern.indexOf('?');
+ if (starIndex < 0 && questionIndex < 0) {
+ // reset pattern match bit if any
+ matchRule &= ~R_PATTERN_MATCH;
+ } else {
+ // force Pattern rule
+ matchRule |= R_PATTERN_MATCH;
+ }
+ if ((matchRule & R_PATTERN_MATCH) != 0) {
+ // remove Camel Case and Prefix match bits if any
+ matchRule &= ~R_CAMELCASE_MATCH;
+ matchRule &= ~R_PREFIX_MATCH;
+ }
+
+ // Verify Camel Case match rule
+ if ((matchRule & R_CAMELCASE_MATCH) != 0) {
+ // Verify sting pattern validity
+ int length = stringPattern.length();
+ boolean validCamelCase = true;
+ boolean uppercase = false;
+ for (int i=0; iSearchEngine.search
+ * and implement the {@link #acceptSearchMatch(SearchMatch)} method, and
+ * possibly override other life cycle methods.
+ *
+ * The search engine calls beginReporting()
when a search starts,
+ * then calls acceptSearchMatch(...)
for each search result, and
+ * finally calls endReporting()
. The order of the search results
+ * is unspecified and may vary from request to request; when displaying results,
+ * clients should not rely on the order but should instead arrange the results
+ * in an order that would be more meaningful to the user.
+ *
+ *
+ * @see SearchEngine
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class SearchRequestor {
+
+ /**
+ * Accepts the given search match.
+ *
+ * @param match the found match
+ * @throws CoreException
+ */
+ public abstract void acceptSearchMatch(SearchMatch match) throws CoreException;
+
+ /**
+ * Notification sent before starting the search action.
+ * Typically, this would tell a search requestor to clear previously
+ * recorded search results.
+ *
+ * The default implementation of this method does nothing. Subclasses
+ * may override.
+ *
+ */
+ public void beginReporting() {
+ // do nothing
+ }
+
+ /**
+ * Notification sent after having completed the search action.
+ * Typically, this would tell a search requestor collector that no more
+ * results will be forthcomping in this search.
+ *
+ * The default implementation of this method does nothing. Subclasses
+ * may override.
+ *
+ */
+ public void endReporting() {
+ // do nothing
+ }
+
+ /**
+ * Intermediate notification sent when the given participant starts to
+ * contribute.
+ *
+ * The default implementation of this method does nothing. Subclasses
+ * may override.
+ *
+ *
+ * @param participant the participant that is starting to contribute
+ */
+ public void enterParticipant(SearchParticipant participant) {
+ // do nothing
+ }
+
+ /**
+ * Intermediate notification sent when the given participant is finished
+ * contributing.
+ *
+ * The default implementation of this method does nothing. Subclasses
+ * may override.
+ *
+ *
+ * @param participant the participant that finished contributing
+ */
+ public void exitParticipant(SearchParticipant participant) {
+ // do nothing
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeDeclarationMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeDeclarationMatch.java
new file mode 100644
index 0000000..5ccf344
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeDeclarationMatch.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a type declaration.
+ * The element is an IType
.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TypeDeclarationMatch extends SearchMatch {
+
+ /**
+ * Creates a new type declaration match.
+ *
+ * @param element the type declaration
+ * @param accuracy one of A_ACCURATE or A_INACCURATE
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public TypeDeclarationMatch(IJavaScriptElement element, int accuracy, int offset, int length, SearchParticipant participant, IResource resource) {
+ super(element, accuracy, offset, length, participant, resource);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameMatch.java
new file mode 100644
index 0000000..7864309
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameMatch.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
+import org.eclipse.wst.jsdt.core.IType;
+
+/**
+ * A match collected while {@link SearchEngine searching} for
+ * all type names methods using a {@link TypeNameRequestor requestor}.
+ *
+ * The type of this match is available from {@link #getType()}.
+ *
+ *
+ * This class is not intended to be overridden by clients.
+ *
+ *
+ * @see TypeNameMatchRequestor
+ * @see SearchEngine#searchAllTypeNames(char[], int, char[], int, int, IJavaScriptSearchScope, TypeNameMatchRequestor, int, org.eclipse.core.runtime.IProgressMonitor)
+ * @see SearchEngine#searchAllTypeNames(char[][], char[][], IJavaScriptSearchScope, TypeNameMatchRequestor, int, org.eclipse.core.runtime.IProgressMonitor)
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class TypeNameMatch {
+
+/**
+ * Returns the matched type's fully qualified name using '.' character
+ * as separator (e.g. package name + '.' enclosing type names + '.' simple name).
+ *
+ * @see #getType()
+ * @see IType#getFullyQualifiedName(char)
+ *
+ * @throws NullPointerException if matched type is null
+ * @return Fully qualified type name of the type
+ */
+public String getFullyQualifiedName() {
+ return getType().getFullyQualifiedName('.');
+}
+
+/**
+ * Returns the modifiers of the matched type.
+ *
+ * This is a handle-only method as neither JavaScript Model nor includepath
+ * initialization is done while calling this method.
+ *
+ * @return the type modifiers
+ */
+public abstract int getModifiers();
+
+/**
+ * Returns the package fragment root of the stored type.
+ * Package fragment root cannot be null and does exist.
+ *
+ * @see #getType()
+ * @see IJavaScriptElement#getAncestor(int)
+ *
+ * @throws NullPointerException if matched type is null
+ * @return the existing javascript model package fragment root (ie. cannot be null
+ * and will return true
to exists()
message).
+ */
+public IPackageFragmentRoot getPackageFragmentRoot() {
+ return (IPackageFragmentRoot) getType().getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT_ROOT);
+}
+
+/**
+ * Returns the package name of the stored type.
+ *
+ * @see #getType()
+ * @see IType#getPackageFragment()
+ *
+ * @throws NullPointerException if matched type is null
+ * @return the package name
+ */
+public String getPackageName() {
+ String name=getType().getElementName();
+ int index=name.lastIndexOf(".");
+ if (index>=0)
+ name=name.substring(0,index);
+ return "";
+}
+
+/**
+ * Returns the name of the stored type.
+ *
+ * @see #getType()
+ * @see IJavaScriptElement#getElementName()
+ *
+ * @throws NullPointerException if matched type is null
+ * @return the type name
+ */
+public String getSimpleTypeName() {
+ String name=getType().getElementName();
+ int index=name.lastIndexOf(".");
+ if (index>=0)
+ name=name.substring(index+1);
+ return name;
+}
+
+/**
+ * Returns a javascript model type handle.
+ * This handle may exist or not, but is not supposed to be null
.
+ *
+ * This is a handle-only method as neither JavaScript Model nor includepath
+ * initializations are done while calling this method.
+ *
+ * @see IType
+ * @return the non-null handle on matched javascript model type.
+ */
+public abstract IType getType();
+
+/**
+ * Name of the type container using '.' character
+ * as separator (e.g. package name + '.' + enclosing type names).
+ *
+ * @see #getType()
+ * @see org.eclipse.wst.jsdt.core.IMember#getDeclaringType()
+ *
+ * @throws NullPointerException if matched type is null
+ * @return name of the type container
+ */
+public String getTypeContainerName() {
+ IType outerType = getType().getDeclaringType();
+ if (outerType != null) {
+ return outerType.getFullyQualifiedName('.');
+ } else {
+ return getType().getPackageFragment().getElementName();
+ }
+}
+
+/**
+ * Returns the matched type's type qualified name using '.' character
+ * as separator (e.g. enclosing type names + '.' + simple name).
+ *
+ * @see #getType()
+ * @see IType#getTypeQualifiedName(char)
+ *
+ * @throws NullPointerException if matched type is null
+ * @return fully qualified type name of the type
+ */
+public String getTypeQualifiedName() {
+ return getType().getTypeQualifiedName('.');
+}
+
+public String getQualifiedName() {
+return getType().getElementName();
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameMatchRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameMatchRequestor.java
new file mode 100644
index 0000000..953eb5b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameMatchRequestor.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+/**
+ * A TypeNameMatchRequestor
collects matches from a searchAllTypeNames
+ * query to a SearchEngine
. Clients must subclass this abstract class and pass an instance to the
+ * {@link SearchEngine#searchAllTypeNames(
+ * char[] packageName,
+ * int packageMatchRule,
+ * char[] typeName,
+ * int typeMatchRule,
+ * int searchFor,
+ * IJavaScriptSearchScope scope,
+ * TypeNameMatchRequestor nameMatchRequestor,
+ * int waitingPolicy,
+ * org.eclipse.core.runtime.IProgressMonitor monitor)} method.
+ * Only top-level and member types are reported. Local types are not reported.
+ *
+ * While {@link TypeNameRequestor} only reports type names information (e.g. package, enclosing types, simple name, modifiers, etc.),
+ * this class reports {@link TypeNameMatch} objects instead, which store this information and can return
+ * an {@link org.eclipse.wst.jsdt.core.IType} handle.
+ *
+ *
+ * This class may be subclassed by clients.
+ *
+ * @see TypeNameMatch
+ * @see TypeNameRequestor
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class TypeNameMatchRequestor {
+ /**
+ * Accepts a type name match ({@link TypeNameMatch}) which contains top-level or a member type
+ * information as package name, enclosing types names, simple type name, modifiers, etc.
+ *
+ * @param match the match which contains all type information
+ */
+ public abstract void acceptTypeNameMatch(TypeNameMatch match);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameRequestor.java
new file mode 100644
index 0000000..71b0fb4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeNameRequestor.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+/**
+ * A TypeNameRequestor
collects search results from a searchAllTypeNames
+ * query to a SearchEngine
. Clients must subclass this abstract class and pass
+ * an instance to the SearchEngine.searchAllTypeNames(...)
method. Only top-level and
+ * member types are reported. Local types are not reported.
+ *
+ * This class may be subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public abstract class TypeNameRequestor {
+ /**
+ * Accepts a top-level or a member type.
+ *
+ * The default implementation of this method does nothing.
+ * Subclasses should override.
+ *
+ *
+ * @param modifiers the modifier flags of the type. Note that for source type,
+ * these flags may slightly differ from thoses get after resolution.
+ * For example an interface defined by interface A {}
,
+ * although obviously public, will be returned false by Flags.isPublic(modifiers)
+ * due to the fact that its declaration does not explicitely define public flag.
+ * @see org.eclipse.wst.jsdt.core.Flags
+ * @param packageName the dot-separated name of the package of the type
+ * @param simpleTypeName the simple name of the type
+ * @param enclosingTypeNames if the type is a member type,
+ * the simple names of the enclosing types from the outer-most to the
+ * direct parent of the type (for example, if the class is x.y.A$B$C then
+ * the enclosing types are [A, B]. This is an empty array if the type
+ * is a top-level type.
+ * @param path the full path to the resource containing the type. If the resource is a .class file
+ * or a source file, this is the full path in the workspace to this resource. If the
+ * resource is an archive (that is, a .zip or .jar file), the path is composed of 2 paths separated
+ * by IJavaScriptSearchScope.JAR_FILE_ENTRY_SEPARATOR
:
+ * the first path is the full OS path to the archive (if it is an external archive),
+ * or the workspace relative IPath
to the archive (if it is an internal archive),
+ * the second path is the path to the resource inside the archive.
+ */
+ public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
+ // do nothing
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeReferenceMatch.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeReferenceMatch.java
new file mode 100644
index 0000000..e8fc008
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/search/TypeReferenceMatch.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.search;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+
+/**
+ * A JavaScript search match that represents a type reference.
+ * The element is the inner-most enclosing member that references this type.
+ *
+ * This class is intended to be instantiated and subclassed by clients.
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public class TypeReferenceMatch extends SearchMatch {
+
+ private IJavaScriptElement localElement;
+ private IJavaScriptElement[] otherElements;
+
+ /**
+ * Creates a new type reference match.
+ *
+ * @param enclosingElement the inner-most enclosing member that references this type
+ * @param accuracy one of {@link #A_ACCURATE} or {@link #A_INACCURATE}
+ * @param offset the offset the match starts at, or -1 if unknown
+ * @param length the length of the match, or -1 if unknown
+ * @param insideDocComment true
if this search match is inside a doc
+ * comment, and false
otherwise
+ * @param participant the search participant that created the match
+ * @param resource the resource of the element
+ */
+ public TypeReferenceMatch(IJavaScriptElement enclosingElement, int accuracy, int offset, int length, boolean insideDocComment, SearchParticipant participant, IResource resource) {
+ super(enclosingElement, accuracy, offset, length, participant, resource);
+ setInsideDocComment(insideDocComment);
+ }
+
+ /**
+ * Returns the local element of this search match.
+ * This may be a local variable which declaring type is the referenced one
+ * or a type parameter which extends it.
+ *
+ * @return the element of the search match, or null
if none or there's
+ * no more specific local element than the element itself ({@link SearchMatch#getElement()}).
+ *
+ */
+ public final IJavaScriptElement getLocalElement() {
+ return this.localElement;
+ }
+
+ /**
+ * Returns other enclosing elements of this search match.
+ *
+ * If {@link #getLocalElement()} is not null
, these may be other
+ * local elements such as additional local variables of a multiple local
+ * variables declaration. Otherwise, these may be other elements such as
+ * additional fields of a multiple fields declaration.
+ *
+ * @return the other elements of the search match, or null
if none
+ *
+ */
+ public final IJavaScriptElement[] getOtherElements() {
+ return this.otherElements;
+ }
+
+ /**
+ * Sets the local element of this search match.
+ *
+ * @param localElement A more specific local element that corresponds to the match,
+ * or null
if none
+ *
+ */
+ public final void setLocalElement(IJavaScriptElement localElement) {
+ this.localElement = localElement;
+ }
+
+ /**
+ * Sets the other elements of this search match.
+ *
+ * @param otherElements the other elements of the match,
+ * or null
if none
+ *
+ */
+ public final void setOtherElements(IJavaScriptElement[] otherElements) {
+ this.otherElements = otherElements;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/IModifierConstants.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/IModifierConstants.java
new file mode 100644
index 0000000..fa3bb1a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/IModifierConstants.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.core.util;
+
+/**
+ * Definition of the modifier constants.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public interface IModifierConstants {
+
+ int ACC_PUBLIC = 0x0001;
+ int ACC_PRIVATE = 0x0002;
+ int ACC_PROTECTED = 0x0004;
+ int ACC_STATIC = 0x0008;
+ int ACC_FINAL = 0x0010;
+ int ACC_SUPER = 0x0020;
+
+ /**
+ * Indicates a variable arity method (added in J2SE 1.5).
+ *
+ */
+ int ACC_VARARGS = 0x0080;
+ int ACC_NATIVE = 0x0100;
+ int ACC_ABSTRACT = 0x0400;
+ int ACC_STRICT = 0x0800;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/JavaScriptUnitSorter.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/JavaScriptUnitSorter.java
new file mode 100644
index 0000000..42721cf
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/JavaScriptUnitSorter.java
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Alex Blewitt - alex_blewitt@yahoo.com https://bugs.eclipse.org/bugs/show_bug.cgi?id=171066
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.util;
+
+import java.util.Comparator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
+import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
+import org.eclipse.wst.jsdt.core.IJavaScriptElement;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.dom.AST;
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+import org.eclipse.wst.jsdt.internal.core.SortElementsOperation;
+
+/**
+ * Operation for sorting members within a javascript unit .
+ *
+ * This class provides all functionality via static members; it is not
+ * intended to be instantiated or subclassed.
+ *
+ *
+ *
+ * Provisional API: This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
+ * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
+ * (repeatedly) as the API evolves.
+ */
+public final class JavaScriptUnitSorter {
+
+ /**
+ * Private constructor to prevent instantiation.
+ */
+ private JavaScriptUnitSorter() {
+ // Not instantiable
+ }
+
+
+ private static void checkASTLevel(int level) {
+ switch (level) {
+ case AST.JLS2 :
+ case AST.JLS3 :
+ break;
+ default :
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Name of auxillary property whose value can be used to determine the
+ * original relative order of two body declarations. This allows a
+ * comparator to preserve the relative positions of certain kinds of
+ * body declarations when required.
+ *
+ * All body declarations passed to the comparator's compare
+ * method by JavaScriptUnitSorter.sort
carry an
+ * Integer-valued property. The body declaration with the lower value
+ * comes before the one with the higher value. The exact numeric value
+ * of these properties is unspecified.
+ *
+ *
+ * Example usage:
+ *
+ * BodyDeclaration b1 = (BodyDeclaration) object1;
+ * BodyDeclaration b2 = (BodyDeclaration) object2;
+ * Integer i1 = (Integer) b1.getProperty(RELATIVE_ORDER);
+ * Integer i2 = (Integer) b2.getProperty(RELATIVE_ORDER);
+ * return i1.intValue() - i2.intValue(); // preserve original order
+ *
+ *
+ *
+ * @see org.eclipse.wst.jsdt.core.dom.BodyDeclaration
+ */
+ public static final String RELATIVE_ORDER = "relativeOrder"; //$NON-NLS-1$
+
+ /**
+ * Reorders the declarations in the given javascript unit according to
+ * the specified AST level. The caller is responsible for arranging in
+ * advance that the given javascript unit is a working copy, and for
+ * saving the changes afterwards.
+ *
+ * Note: Reordering the members within a type declaration might be
+ * more than a cosmetic change and could have potentially serious
+ * repercussions. Firstly, the order in which the fields of a type are
+ * initialized is significant in the JavaScript language; reordering fields
+ * and initializers may result in compilation errors or change the execution
+ * behavior of the code. Secondly, reordering a class's members may affect
+ * how its instances are serialized. This operation should therefore be used
+ * with caution and due concern for potential negative side effects.
+ *
+ *
+ * The optional positions
array contains a non-decreasing
+ * ordered list of character-based source positions within the compilation
+ * unit's source code string. Upon return from this method, the positions in
+ * the array reflect the corresponding new locations in the modified source
+ * code string. Note that this operation modifies the given array in place.
+ *
+ *
+ * The compare
method of the given comparator is passed pairs
+ * of body declarations (subclasses of BodyDeclaration
)
+ * representing body declarations at the same level. The nodes are from an
+ * AST of the specified level
+ * ({@link org.eclipse.wst.jsdt.core.dom.ASTParser#newParser(int)}. Clients
+ * will generally specify AST.JLS3 since that will cover all constructs found
+ * in JavaScript 1.0, 1.1, 1.2, 1.3, 1.4, and 1.5 source code.
+ * The comparator is called on body declarations of nested classes, including
+ * anonymous and local classes, but always at the same level. Clients need to provide
+ * a comparator implementation (there is no standard comparator). The
+ * RELATIVE_ORDER
property attached to these AST nodes afforts
+ * the comparator a way to preserve the original relative order.
+ *
+ *
+ * The body declarations passed as parameters to the comparator
+ * always carry at least the following minimal signature information:
+ *
+ *
+ *
+ * TypeDeclaration
+ * modifiers, isInterface, name, superclass,
+ * superInterfaces, typeParameters
+ * RELATIVE_ORDER property
+ *
+ *
+ * FieldDeclaration
+ * modifiers, type, fragments
+ * (VariableDeclarationFragments
+ * with name only)
+ * RELATIVE_ORDER property
+ *
+ *
+ * FunctionDeclaration
+ * modifiers, isConstructor, returnType, name,
+ * typeParameters, parameters
+ * (SingleVariableDeclarations with name, type, and modifiers only),
+ * thrownExceptions
+ * RELATIVE_ORDER property
+ *
+ *
+ * Initializer
+ * modifiers
+ * RELATIVE_ORDER property
+ *
+ *
+ * AnnotationTypeDeclaration
+ * modifiers, name
+ * RELATIVE_ORDER property
+ *
+ *
+ * AnnotationTypeMemberDeclaration
+ * modifiers, name, type, default
+ * RELATIVE_ORDER property
+ *
+ *
+ * EnumDeclaration
+ * modifiers, name, superInterfaces
+ * RELATIVE_ORDER property
+ *
+ *
+ * EnumConstantDeclaration
+ * modifiers, name, arguments
+ * RELATIVE_ORDER property
+ *
+ *
+ * Clients should not rely on the AST nodes being properly parented or on
+ * having source range information. (Future releases may provide options
+ * for requesting additional information like source positions, full ASTs,
+ * non-recursive sorting, etc.)
+ *
+ *
+ * @param level the AST level; one of the AST LEVEL constants
+ * @param compilationUnit the given javascript unit , which must be a
+ * working copy
+ * @param positions an array of source positions to map, or
+ * null
if none. If supplied, the positions must
+ * character-based source positions within the original source code for
+ * the given javascript unit , arranged in non-decreasing order.
+ * The array is updated in place when this method returns to reflect the
+ * corresponding source positions in the permuted source code string
+ * (but not necessarily any longer in non-decreasing order).
+ * @param comparator the comparator capable of ordering
+ * BodyDeclaration
s; this comparator is passed AST nodes
+ * from an AST of the specified AST level
+ * @param options bitwise-or of option flags; 0
for default
+ * behavior (reserved for future growth)
+ * @param monitor the progress monitor to notify, or null
if
+ * none
+ * @exception JavaScriptModelException if the javascript unit could not be
+ * sorted. Reasons include:
+ *
+ * - The given javascript unit does not exist (ELEMENT_DOES_NOT_EXIST)
+ * - The given javascript unit is not a working copy (INVALID_ELEMENT_TYPES)
+ * - A
CoreException
occurred while accessing the underlying
+ * resource
+ *
+ * @exception IllegalArgumentException if the given javascript unit is null
+ * or if the given comparator is null, or if level
is not one of
+ * the AST JLS level constants.
+ * @see org.eclipse.wst.jsdt.core.dom.BodyDeclaration
+ * @see #RELATIVE_ORDER
+ *
+ */
+ public static void sort(int level, IJavaScriptUnit compilationUnit,
+ int[] positions,
+ Comparator comparator,
+ int options,
+ IProgressMonitor monitor) throws JavaScriptModelException {
+ if (compilationUnit == null || comparator == null) {
+ throw new IllegalArgumentException();
+ }
+ checkASTLevel(level);
+ IJavaScriptUnit[] compilationUnits = new IJavaScriptUnit[] { compilationUnit };
+ SortElementsOperation operation = new SortElementsOperation(level, compilationUnits, positions, comparator);
+ operation.runOperation(monitor);
+ }
+
+ /**
+ * Reorders the declarations in the given javascript unit according to the
+ * specified comparator. The caller is responsible for arranging in advance
+ * that the given javascript unit is a working copy, and for applying the
+ * returned TextEdit afterwards.
+ *
+ * Note: Reordering the members within a type declaration might be
+ * more than a cosmetic change and could have potentially serious
+ * repercussions. Firstly, the order in which the fields of a type are
+ * initialized is significant in the JavaScript language; reordering fields and
+ * initializers may result in compilation errors or change the execution
+ * behavior of the code. Secondly, reordering a class's members may affect
+ * how its instances are serialized. This operation should therefore be used
+ * with caution and due concern for potential negative side effects.
+ *
+ *
+ * The compare
method of the given comparator is passed pairs
+ * of body declarations (subclasses of BodyDeclaration
)
+ * representing body declarations at the same level.
+ * The comparator is called on body declarations of nested classes,
+ * including anonymous and local classes, but always at the same level.
+ * Clients need to provide a comparator implementation (there is no standard
+ * comparator). The RELATIVE_ORDER
property attached to these
+ * AST nodes affords the comparator a way to preserve the original relative
+ * order.
+ *
+ *
+ * The body declarations passed as parameters to the comparator always carry
+ * at least the following minimal signature information:
+ *
+ *
+ * TypeDeclaration
+ * modifiers, isInterface, name, superclass,
+ * superInterfaces, typeParameters
+ * RELATIVE_ORDER property
+ *
+ *
+ * FieldDeclaration
+ * modifiers, type, fragments
+ * (VariableDeclarationFragments
+ * with name only)
+ * RELATIVE_ORDER property
+ *
+ *
+ * FunctionDeclaration
+ * modifiers, isConstructor, returnType, name,
+ * typeParameters, parameters
+ * (SingleVariableDeclarations with name, type, and modifiers only),
+ * thrownExceptions
+ * RELATIVE_ORDER property
+ *
+ *
+ * Initializer
+ * modifiers
+ * RELATIVE_ORDER property
+ *
+ *
+ * AnnotationTypeDeclaration
+ * modifiers, name
+ * RELATIVE_ORDER property
+ *
+ *
+ * AnnotationTypeMemberDeclaration
+ * modifiers, name, type, default
+ * RELATIVE_ORDER property
+ *
+ *
+ * EnumDeclaration
+ * modifiers, name, superInterfaces
+ * RELATIVE_ORDER property
+ *
+ *
+ * EnumConstantDeclaration
+ * modifiers, name, arguments
+ * RELATIVE_ORDER property
+ *
+ *
+ *
+ *
+ * @param unit
+ * the JavaScriptUnit to sort
+ * @param comparator
+ * the comparator capable of ordering
+ * BodyDeclaration
s; this comparator is passed
+ * AST nodes from an AST of the specified AST level
+ * @param options
+ * bitwise-or of option flags; 0
for default
+ * behavior (reserved for future growth)
+ * @param group
+ * the text edit group to use when generating text edits, or null
+ * @param monitor
+ * the progress monitor to notify, or null
if none
+ * @return a TextEdit describing the required edits to do the sort, or null
+ * if sorting is not required
+ * @exception JavaScriptModelException
+ * if the javascript unit could not be sorted. Reasons
+ * include:
+ *
+ * - The given unit was not created from a IJavaScriptUnit (INVALID_ELEMENT_TYPES)
+ *
+ * @exception IllegalArgumentException
+ * if the given javascript unit is null or if the given
+ * comparator is null, or if options
is not one
+ * of the supported levels.
+ * @see org.eclipse.wst.jsdt.core.dom.BodyDeclaration
+ * @see #RELATIVE_ORDER
+ *
+ */
+ public static TextEdit sort(JavaScriptUnit unit,
+ Comparator comparator,
+ int options,
+ TextEditGroup group,
+ IProgressMonitor monitor) throws JavaScriptModelException {
+ if (unit == null || comparator == null) {
+ throw new IllegalArgumentException();
+ }
+ SortElementsOperation operation = new SortElementsOperation(AST.JLS3, new IJavaScriptElement[] { unit.getJavaElement() }, null, comparator);
+ return operation.calculateEdit(unit, group);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/SequenceReader.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/SequenceReader.java
new file mode 100644
index 0000000..c94a815
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/core/util/SequenceReader.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.core.util;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Provides the contents of multiple Readers in sequence.
+ */
+public class SequenceReader extends Reader {
+ private Reader[] fReaders;
+ private Reader fCurrentReader;
+
+ /**
+ * @param readers
+ * the readers from which to read
+ */
+ public SequenceReader(Reader[] readers) {
+ fReaders = readers;
+ if (fReaders.length > 0) {
+ fCurrentReader = fReaders[0];
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.Reader#close()
+ */
+ public void close() throws IOException {
+ if (fCurrentReader != null) {
+ for (int i = 0; i <= indexOf(fCurrentReader); i++) {
+ fReaders[i].close();
+ }
+ }
+ }
+
+ private int indexOf(Reader r) {
+ for (int i = 0; i < fReaders.length; i++) {
+ if (fReaders[i] == r) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.io.Reader#read(char[], int, int)
+ */
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ if (fCurrentReader != null) {
+ int bufIndex = off;
+ int read = 0;
+ for (bufIndex = off; bufIndex - off < len; bufIndex++) {
+ int c = primRead();
+ if (c != -1) {
+ read++;
+ cbuf[bufIndex] = (char) c;
+ }
+ else if (read == 0) {
+ return -1;
+ }
+ }
+ return read;
+ }
+ return -1;
+ }
+
+ /**
+ * @return
+ */
+ private int primRead() {
+ int c = -1;
+ try {
+ c = fCurrentReader.read();
+ }
+ catch (IOException e) {
+ }
+ if (c == -1) {
+ int index = indexOf(fCurrentReader);
+ if (index > -1 && index < fReaders.length - 1) {
+ fCurrentReader = fReaders[index + 1];
+ c = primRead();
+ }
+ }
+ return c;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java
new file mode 100644
index 0000000..e506ce3
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/CompletionEngine.java
@@ -0,0 +1,7597 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Michael Spector Bug 242989
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.CompletionContext;
+import org.eclipse.wst.jsdt.core.CompletionFlags;
+import org.eclipse.wst.jsdt.core.CompletionProposal;
+import org.eclipse.wst.jsdt.core.CompletionRequestor;
+import org.eclipse.wst.jsdt.core.Flags;
+import org.eclipse.wst.jsdt.core.IAccessRule;
+import org.eclipse.wst.jsdt.core.IFunction;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.Signature;
+import org.eclipse.wst.jsdt.core.UnimplementedException;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionNodeFound;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnArgumentName;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnBrankStatementLabel;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnClassLiteralAccess;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnFieldName;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnFieldType;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnImportReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadoc;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocParamNameReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnJavadocTag;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnKeyword;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnLocalName;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnMemberAccess;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnMessageSend;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnMessageSendName;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnMethodName;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnQualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnQualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnQualifiedType;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnSingleNameReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnSingleTypeName;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionOnStringLiteral;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionParser;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionScanner;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.InvalidCursorLocation;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.Engine;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.Keywords;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.InstanceOfExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocImplicitTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BinaryTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FunctionTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ImportBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MetatdataTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemMethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocTagConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.SourceTypeConverter;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.wst.jsdt.internal.compiler.util.ObjectVector;
+import org.eclipse.wst.jsdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.wst.jsdt.internal.core.BasicCompilationUnit;
+import org.eclipse.wst.jsdt.internal.core.BinaryTypeConverter;
+import org.eclipse.wst.jsdt.internal.core.INamingRequestor;
+import org.eclipse.wst.jsdt.internal.core.InternalNamingConventions;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+import org.eclipse.wst.jsdt.internal.core.SourceMethod;
+import org.eclipse.wst.jsdt.internal.core.SourceMethodElementInfo;
+import org.eclipse.wst.jsdt.internal.core.SourceType;
+import org.eclipse.wst.jsdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.wst.jsdt.internal.oaametadata.ClassData;
+import org.eclipse.wst.jsdt.internal.oaametadata.Method;
+
+/**
+ * This class is the entry point for source completions.
+ * It contains two public APIs used to call CodeAssist on a given source with
+ * a given environment, assisting position and storage (and possibly options).
+ */
+public final class CompletionEngine
+ extends Engine
+ implements ISearchRequestor, TypeConstants , TerminalTokens , RelevanceConstants, SuffixConstants {
+
+ public class CompletionProblemFactory extends DefaultProblemFactory {
+ private int lastErrorStart;
+
+ private boolean checkProblems = false;
+ public boolean hasForbiddenProblems = false;
+ public boolean hasAllowedProblems = false;
+
+ public CompletionProblemFactory(Locale loc) {
+ super(loc);
+ }
+
+ public CategorizedProblem createProblem(
+ char[] originatingFileName,
+ int problemId,
+ String[] problemArguments,
+ String[] messageArguments,
+ int severity,
+ int start,
+ int end,
+ int lineNumber,
+ int columnNumber) {
+
+ CategorizedProblem pb = super.createProblem(
+ originatingFileName,
+ problemId,
+ problemArguments,
+ messageArguments,
+ severity,
+ start,
+ end,
+ lineNumber,
+ columnNumber);
+ int id = pb.getID();
+ if (CompletionEngine.this.actualCompletionPosition > start
+ && this.lastErrorStart < start
+ && pb.isError()
+ && (id & IProblem.Syntax) == 0
+ && (CompletionEngine.this.fileName == null || CharOperation.equals(CompletionEngine.this.fileName, originatingFileName))) {
+
+ CompletionEngine.this.problem = pb;
+ this.lastErrorStart = start;
+ }
+ if (this.checkProblems && !this.hasForbiddenProblems) {
+ switch (id) {
+ case IProblem.UsingDeprecatedType:
+ this.hasForbiddenProblems =
+ CompletionEngine.this.options.checkDeprecation;
+ break;
+ case IProblem.NotVisibleType:
+ this.hasForbiddenProblems =
+ CompletionEngine.this.options.checkVisibility;
+ break;
+ case IProblem.ForbiddenReference:
+ this.hasForbiddenProblems =
+ CompletionEngine.this.options.checkForbiddenReference;
+ break;
+ case IProblem.DiscouragedReference:
+ this.hasForbiddenProblems =
+ CompletionEngine.this.options.checkDiscouragedReference;
+ break;
+ default:
+ if ((severity & ProblemSeverities.Optional) != 0) {
+ this.hasAllowedProblems = true;
+ } else {
+ this.hasForbiddenProblems = true;
+ }
+
+ break;
+ }
+ }
+
+ return pb;
+ }
+
+ public void startCheckingProblems() {
+ this.checkProblems = true;
+ this.hasForbiddenProblems = false;
+ this.hasAllowedProblems = false;
+ }
+
+ public void stopCheckingProblems() {
+ this.checkProblems = false;
+ }
+ }
+
+ private static class AcceptedBinding {
+ public AcceptedBinding(
+ char[] packageName,
+ char[] simpleTypeName,
+ char[][] enclosingTypeNames,
+ int modifiers,
+ int accessibility) {
+ this.packageName = packageName;
+ this.simpleTypeName = simpleTypeName;
+ this.enclosingTypeNames = enclosingTypeNames;
+ this.modifiers = modifiers;
+ this.accessibility = accessibility;
+ this.bindingType=Binding.TYPE;
+ }
+ public AcceptedBinding(
+ int bindingType,
+ char[] packageName,
+ char[] simpleTypeName,
+ int modifiers,
+ int accessibility) {
+ this.bindingType=bindingType;
+ this.packageName = packageName;
+ this.simpleTypeName = simpleTypeName;
+ this.modifiers = modifiers;
+ this.accessibility = accessibility;
+ }
+ public char[] packageName;
+ public char[] simpleTypeName;
+ public char[][] enclosingTypeNames;
+ public int modifiers;
+ public int accessibility;
+
+ public boolean mustBeQualified = false;
+ public char[] fullyQualifiedName = null;
+ public char[] qualifiedTypeName = null;
+ public int bindingType;
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('{');
+ buffer.append(packageName);
+ buffer.append(',');
+ buffer.append(simpleTypeName);
+ buffer.append(',');
+ buffer.append(CharOperation.concatWith(enclosingTypeNames, '.'));
+ buffer.append('}');
+ return buffer.toString();
+ }
+ }
+
+ public HashtableOfObject typeCache;
+
+ public static boolean DEBUG = false;
+ public static boolean PERF = false;
+
+ // temporary constants to quickly disabled polish features if necessary
+ public final static boolean NO_TYPE_COMPLETION_ON_EMPTY_TOKEN = false;
+
+ private final static char[] ERROR_PATTERN = "*error*".toCharArray(); //$NON-NLS-1$
+ private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray(); //$NON-NLS-1$
+ private final static char[] SEMICOLON = new char[] { ';' };
+
+ private final static char[] CLASS = "Class".toCharArray(); //$NON-NLS-1$
+ private final static char[] VOID = "void".toCharArray(); //$NON-NLS-1$
+
+ private final static char[] VARARGS = "...".toCharArray(); //$NON-NLS-1$
+
+ private final static char[] IMPORT = "import".toCharArray(); //$NON-NLS-1$
+ private final static char[] STATIC = "static".toCharArray(); //$NON-NLS-1$
+ private final static char[] ON_DEMAND = ".*".toCharArray(); //$NON-NLS-1$
+ private final static char[] IMPORT_END = ";\n".toCharArray(); //$NON-NLS-1$
+
+ private final static char[] JAVA_LANG_OBJECT_SIGNATURE =
+ createTypeSignature(
+ new char[]{},
+ OBJECT);
+ private final static char[] JAVA_LANG_NAME =
+ CharOperation.concatWith(JAVA_LANG, '.');
+
+
+ private final static int NONE = 0;
+ private final static int SUPERTYPE = 1;
+ private final static int SUBTYPE = 2;
+
+ private final static int FIELD = 0;
+ private final static int LOCAL = 1;
+ private final static int ARGUMENT = 2;
+
+ int expectedTypesPtr = -1;
+ TypeBinding[] expectedTypes = new TypeBinding[1];
+ int expectedTypesFilter;
+ boolean hasJavaLangObjectAsExpectedType = false;
+ int uninterestingBindingsPtr = -1;
+ Binding[] uninterestingBindings = new Binding[1];
+ int forbbidenBindingsPtr = -1;
+ Binding[] forbbidenBindings = new Binding[1];
+ int forbbidenBindingsFilter;
+
+ ImportBinding[] favoriteReferenceBindings;
+
+ boolean assistNodeIsClass;
+ boolean assistNodeIsException;
+ boolean assistNodeIsConstructor;
+ boolean assistNodeIsSuperType;
+ int assistNodeInJavadoc = 0;
+ boolean assistNodeCanBeSingleMemberAnnotation = false;
+
+ long targetedElement;
+
+ IJavaScriptProject javaProject;
+ CompletionParser parser;
+ CompletionRequestor requestor;
+ CompletionProblemFactory problemFactory;
+ ProblemReporter problemReporter;
+ char[] source;
+ char[] completionToken;
+ char[] qualifiedCompletionToken;
+ boolean resolvingImports = false;
+ boolean insideQualifiedReference = false;
+ boolean noProposal = true;
+ CategorizedProblem problem = null;
+ char[] fileName = null;
+ char [][]packageName;
+ int startPosition, actualCompletionPosition, endPosition, offset;
+ int javadocTagPosition; // Position of previous tag while completing in javadoc
+ HashtableOfObject knownPkgs = new HashtableOfObject(10);
+ HashtableOfObject knownTypes = new HashtableOfObject(10);
+ Scanner nameScanner;
+
+ /**
+ * Constructors accepted by {@link #acceptConstructor(int, char[], int, char[], char[][], char[][], String, AccessRestriction)}
+ * to be processed by {@link #acceptConstructors(Scope)}
+ */
+ private ObjectVector acceptedConstructors;
+
+ static final char[] classField = "class".toCharArray(); //$NON-NLS-1$
+ static final char[] lengthField = "length".toCharArray(); //$NON-NLS-1$
+ static final char[] cloneMethod = "clone".toCharArray(); //$NON-NLS-1$
+ static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$
+ static final char[] THROWS = "throws".toCharArray(); //$NON-NLS-1$
+
+ static InvocationSite FakeInvocationSite = new InvocationSite(){
+ public boolean isSuperAccess(){ return false; }
+ public boolean isTypeAccess(){ return false; }
+ public void setActualReceiverType(ReferenceBinding receiverType) {/* empty */}
+ public void setDepth(int depth){/* empty */}
+ public void setFieldIndex(int depth){/* empty */}
+ public int sourceStart() { return 0; }
+ public int sourceEnd() { return 0; }
+ };
+
+ /**
+ * When performing an index search for binding matches this is
+ * where the results will be stored
+ */
+ private ObjectVector acceptedBindings;
+
+ /**
+ * The CompletionEngine is responsible for computing source completions.
+ *
+ * It requires a searchable name environment, which supports some
+ * specific search APIs, and a requestor to feed back the results to a UI.
+ *
+ * @param nameEnvironment org.eclipse.wst.jsdt.internal.codeassist.ISearchableNameEnvironment
+ * used to resolve type/package references and search for types/packages
+ * based on partial names.
+ *
+ * @param requestor org.eclipse.wst.jsdt.internal.codeassist.ICompletionRequestor
+ * since the engine might produce answers of various forms, the engine
+ * is associated with a requestor able to accept all possible completions.
+ *
+ * @param settings java.util.Map
+ * set of options used to configure the code assist engine.
+ */
+ public CompletionEngine(
+ SearchableEnvironment nameEnvironment,
+ CompletionRequestor requestor,
+ Map settings,
+ IJavaScriptProject javaProject) {
+ super(settings);
+ this.javaProject = javaProject;
+ this.requestor = requestor;
+ this.nameEnvironment = nameEnvironment;
+ this.typeCache = new HashtableOfObject(5);
+
+ this.problemFactory = new CompletionProblemFactory(Locale.getDefault());
+ this.problemReporter = new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ this.compilerOptions,
+ problemFactory);
+ this.lookupEnvironment =
+ new LookupEnvironment(this, this.compilerOptions, this.problemReporter, nameEnvironment);
+ this.parser =
+ new CompletionParser(this.problemReporter);
+ this.nameScanner =
+ new Scanner(
+ false /*comment*/,
+ false /*whitespace*/,
+ false /*nls*/,
+ this.compilerOptions.sourceLevel,
+ null /*taskTags*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+ }
+
+ /**
+ * One result of the search consists of a new type.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.I".
+ * The default package is represented by an empty array.
+ */
+ public void acceptType(
+ char[] packageName,
+ char[] fileName,
+ char[] simpleTypeName,
+ char[][] enclosingTypeNames,
+ int modifiers,
+ AccessRestriction accessRestriction) {
+
+ if (this.options.checkDeprecation && (modifiers & ClassFileConstants.AccDeprecated) != 0) return;
+
+ if (this.options.checkVisibility) {
+ if((modifiers & ClassFileConstants.AccPublic) == 0) {
+ if((modifiers & ClassFileConstants.AccPrivate) != 0)
+ return;
+
+ //char[] currentPackage = CharOperation.concatWith(this.unitScope.getDefaultPackage().compoundName, '.');
+ //if(!CharOperation.equals(packageName, currentPackage)) return;
+ }
+ }
+
+ int accessibility = IAccessRule.K_ACCESSIBLE;
+ if(accessRestriction != null) {
+ switch (accessRestriction.getProblemId()) {
+ case IProblem.ForbiddenReference:
+ if (this.options.checkForbiddenReference) {
+ return;
+ }
+ accessibility = IAccessRule.K_NON_ACCESSIBLE;
+ break;
+ case IProblem.DiscouragedReference:
+ if (this.options.checkDiscouragedReference) {
+ return;
+ }
+ accessibility = IAccessRule.K_DISCOURAGED;
+ break;
+ }
+ }
+
+ if(this.acceptedBindings == null) {
+ this.acceptedBindings = new ObjectVector();
+ }
+ char[] fullyQualifiedName = simpleTypeName;
+ if(CharOperation.indexOf('.', simpleTypeName) < 0) {
+ fullyQualifiedName = CharOperation.concat(packageName, simpleTypeName, '.');
+ }
+ this.acceptedBindings.add(new AcceptedBinding(packageName, fullyQualifiedName, enclosingTypeNames, modifiers, accessibility));
+ }
+
+ public void acceptBinding(
+ char[] packageName,
+ char[] fileName,
+ char[] simpleTypeName,
+ int bindingType,
+ int modifiers,
+ AccessRestriction accessRestriction) {
+
+ if (this.options.checkDeprecation && (modifiers & ClassFileConstants.AccDeprecated) != 0) return;
+
+ if (this.options.checkVisibility) {
+ if((modifiers & ClassFileConstants.AccPublic) == 0) {
+ if((modifiers & ClassFileConstants.AccPrivate) != 0) return;
+
+ char[] currentPackage = CharOperation.concatWith(this.unitScope.getDefaultPackage().compoundName, '.');
+ if(!CharOperation.equals(packageName, currentPackage)) return;
+ }
+ }
+
+ int accessibility = IAccessRule.K_ACCESSIBLE;
+ if(accessRestriction != null) {
+ switch (accessRestriction.getProblemId()) {
+ case IProblem.ForbiddenReference:
+ if (this.options.checkForbiddenReference) {
+ return;
+ }
+ accessibility = IAccessRule.K_NON_ACCESSIBLE;
+ break;
+ case IProblem.DiscouragedReference:
+ if (this.options.checkDiscouragedReference) {
+ return;
+ }
+ accessibility = IAccessRule.K_DISCOURAGED;
+ break;
+ }
+ }
+
+ if(acceptedBindings == null) {
+ acceptedBindings = new ObjectVector();
+ }
+ acceptedBindings.add(new AcceptedBinding(bindingType,packageName, simpleTypeName, modifiers, accessibility));
+ }
+
+ private void acceptTypes(Scope scope) {
+ if(this.acceptedBindings == null) return;
+
+ int length = this.acceptedBindings.size();
+
+ if(length == 0) return;
+
+ HashtableOfObject onDemandFound = new HashtableOfObject();
+
+ next : for (int i = 0; i < length; i++) {
+ AcceptedBinding acceptedType = (AcceptedBinding)this.acceptedBindings.elementAt(i);
+ if (acceptedType.bindingType!=Binding.TYPE)
+ continue;
+ char[] packageName = acceptedType.packageName;
+ char[] simpleTypeName = acceptedType.simpleTypeName;
+ char[][] enclosingTypeNames = acceptedType.enclosingTypeNames;
+ int modifiers = acceptedType.modifiers;
+ int accessibility = acceptedType.accessibility;
+
+ char[] typeName;
+ char[] flatEnclosingTypeNames;
+ if(enclosingTypeNames == null || enclosingTypeNames.length == 0) {
+ flatEnclosingTypeNames = null;
+ typeName = simpleTypeName;
+ } else {
+ flatEnclosingTypeNames = CharOperation.concatWith(acceptedType.enclosingTypeNames, '.');
+ typeName = CharOperation.concat(flatEnclosingTypeNames, simpleTypeName, '.');
+ }
+
+ // only need to combine package and type name if the name is not already qualified
+ // in most cases, if not all, it will already be in qualified state
+ char[] fullyQualifiedName = typeName;
+ if(CharOperation.indexOf('.', typeName) < 0) {
+ fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
+ }
+
+ if (this.knownTypes.containsKey(fullyQualifiedName)) continue next;
+
+ this.knownTypes.put(fullyQualifiedName, this);
+
+ if (this.resolvingImports) {
+ char[] completionName = CharOperation.concat(fullyQualifiedName, new char[] { ';' });
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(accessibility);
+ if(insideQualifiedReference) {
+ relevance += computeRelevanceForCaseMatching(this.completionToken, fullyQualifiedName);
+ } else {
+ relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName);
+ }
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance);
+ }
+ } else {
+ if(!this.importCachesInitialized) {
+ this.initializeImportCaches();
+ }
+
+ for (int j = 0; j < this.importCacheCount; j++) {
+ char[][] importName = this.importsCache[j];
+ if(CharOperation.equals(typeName, importName[0])) {
+ proposeType(
+ packageName,
+ simpleTypeName,
+ modifiers,
+ accessibility,
+ typeName,
+ fullyQualifiedName,
+ !CharOperation.equals(fullyQualifiedName, importName[1]),
+ scope);
+ continue next;
+ }
+ }
+
+
+ //if ((enclosingTypeNames == null || enclosingTypeNames.length == 0 ) && CharOperation.equals(this.currentPackageName, packageName)) {
+ proposeType(
+ packageName,
+ simpleTypeName,
+ modifiers,
+ accessibility,
+ typeName,
+ fullyQualifiedName,
+ true,scope);
+ continue next;
+ }
+ }
+ char[][] keys = onDemandFound.keyTable;
+ Object[] values = onDemandFound.valueTable;
+ int max = keys.length;
+ for (int i = 0; i < max; i++) {
+ if(keys[i] != null) {
+ AcceptedBinding value = (AcceptedBinding) values[i];
+ if(value != null) {
+ proposeType(
+ value.packageName,
+ value.simpleTypeName,
+ value.modifiers,
+ value.accessibility,
+ value.qualifiedTypeName,
+ value.fullyQualifiedName,
+ value.mustBeQualified, scope);
+ }
+ }
+ }
+ this.acceptedBindings = null; // reset
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor(
+ * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void acceptConstructor(
+ int modifiers,
+ char[] typeName,
+ int parameterCount,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ String path,
+ AccessRestriction accessRestriction) {
+
+ int accessibility = IAccessRule.K_ACCESSIBLE;
+ if(accessRestriction != null) {
+ switch (accessRestriction.getProblemId()) {
+ case IProblem.ForbiddenReference:
+ if (this.options.checkForbiddenReference) {
+ return;
+ }
+ accessibility = IAccessRule.K_NON_ACCESSIBLE;
+ break;
+ case IProblem.DiscouragedReference:
+ if (this.options.checkDiscouragedReference) {
+ return;
+ }
+ accessibility = IAccessRule.K_DISCOURAGED;
+ break;
+ }
+ }
+
+ if(this.acceptedConstructors == null) {
+ this.acceptedConstructors = new ObjectVector();
+ }
+ this.acceptedConstructors.add(
+ new AcceptedConstructor(
+ modifiers,
+ typeName,
+ parameterCount,
+ parameterTypes,
+ parameterNames,
+ accessibility));
+ }
+
+ /**
+ * Creates proposals for all of the constructors accepted by
+ * {@link #acceptConstructor(int, char[], int, char[][], char[][], String, AccessRestriction)}.
+ *
+ * @see #acceptConstructor(int, char[], int, char[][], char[][], String, AccessRestriction)
+ */
+ private void acceptConstructors() {
+ int length;
+ if(this.acceptedConstructors != null && (length = this.acceptedConstructors.size()) > 0) {
+ for (int i = 0; i < length; i++) {
+ AcceptedConstructor acceptedConstructor = (AcceptedConstructor)this.acceptedConstructors.elementAt(i);
+
+ //decide if constructor should be proposed based on visibility rules
+ boolean proposeConstructor = true;
+ if (this.options.checkVisibility) {
+ final int modifiers = acceptedConstructor.modifiers;
+ proposeConstructor = !(((modifiers & ClassFileConstants.AccPublic) == 0) &&
+ ((modifiers & ClassFileConstants.AccPrivate) != 0));
+ }
+
+ if (proposeConstructor) {
+ proposeConstructor(acceptedConstructor);
+ }
+ }
+ }
+ }
+
+ public void acceptUnresolvedName(char[] name) {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution(false);
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(completionToken, name);
+ relevance += computeRelevanceForQualification(false);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable
+ CompletionEngine.this.noProposal = false;
+ if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
+ CompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.LOCAL_VARIABLE_REF, CompletionEngine.this.actualCompletionPosition);
+ proposal.setSignature(JAVA_LANG_OBJECT_SIGNATURE);
+ proposal.setPackageName(JAVA_LANG_NAME);
+ proposal.setTypeName(OBJECT);
+ proposal.setName(name);
+ proposal.setCompletion(name);
+ proposal.setFlags(Flags.AccDefault);
+ proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset);
+ proposal.setRelevance(relevance);
+ CompletionEngine.this.requestor.accept(proposal);
+ if(DEBUG) {
+ CompletionEngine.this.printDebug(proposal);
+ }
+ }
+ }
+
+
+ /**
+ * When doing an index search for bindings this is where the results end up.
+ *
+ * @param name the name of the binding
+ * @param exactMatch true
if an exact match is needed, false
otherwise
+ * @param prefixRequired
+ */
+ private void acceptBindings(char[] name,boolean exactMatch, boolean prefixRequired) {
+
+ if(this.acceptedBindings == null) return;
+
+ int length = this.acceptedBindings.size();
+
+ if(length == 0) return;
+
+
+ for (int i = 0; i < length; i++) {
+ AcceptedBinding acceptedType = (AcceptedBinding)this.acceptedBindings.elementAt(i);
+ char[] packageName = acceptedType.packageName;
+ char[] bindingName = acceptedType.simpleTypeName;
+ char[][] enclosingTypeNames = acceptedType.enclosingTypeNames;
+ int modifiers = acceptedType.modifiers;
+ if (packageName==null)
+ packageName=new char[0];
+
+
+ Binding binding1 = this.unitScope.getBinding(packageName, Binding.PACKAGE, FakeInvocationSite, false);
+ Binding binding2=null;
+ if (binding1 instanceof PackageBinding) {
+ PackageBinding packageBinding = (PackageBinding) binding1;
+ binding2 = packageBinding.getBinding(bindingName, acceptedType.bindingType);
+ if (binding2==null)
+ continue;
+ }
+
+ switch (acceptedType.bindingType)
+ {
+ case Binding.METHOD:
+ {
+ char[] completion = bindingName;
+ if (!exactMatch) {
+ if (this.source != null
+ && this.source.length > this.endPosition
+ && this.source[this.endPosition] == '(')
+ completion = bindingName;
+ else
+ completion = CharOperation.concat(bindingName, new char[] { '(', ')' });
+ } else {
+ if(prefixRequired && (this.source != null)) {
+ completion = CharOperation.subarray(this.source, this.startPosition, this.endPosition);
+ } else {
+ this.startPosition = this.endPosition;
+ }
+ }
+
+ if (binding2 instanceof MethodBinding && binding2.isValidBinding()) {
+ MethodBinding method = (MethodBinding) binding2;
+
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForInterestingProposal();
+ if (name != null) relevance += computeRelevanceForCaseMatching(name, bindingName);
+ relevance += computeRelevanceForExpectingType(method.returnType);
+ relevance += computeRelevanceForQualification(prefixRequired);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ //figure out the parameters
+ int parametersLength=method.original().parameters.length;
+ char[][] parameterPackageNames = new char[parametersLength][];
+ char[][] parameterFullTypeNames = new char[parametersLength][];
+ for (int j = 0; j < parametersLength; j++) {
+ TypeBinding type = method.parameters[j];
+ parameterPackageNames[j] = type.qualifiedPackageName();
+ parameterFullTypeNames[j] = type.qualifiedSourceName();
+ }
+ char[][] parameterNames = findMethodParameterNames(method, parameterFullTypeNames);
+
+ this.noProposal = false;
+ // Standard proposal
+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(packageName);
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterFullTypeNames);
+
+ if(method.returnType!=null) {
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ }else {
+ proposal.setTypeName(null);
+ }
+
+
+ proposal.setName(bindingName);
+ proposal.setCompletion(completion);
+ proposal.setFlags(modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ proposal.setIsContructor(method.isConstructor());
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Javadoc proposal
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_METHOD_REF)) {
+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterFullTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setName(bindingName);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags( modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ proposal.setIsContructor(method.isConstructor());
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }//end if method binding
+ else
+ {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForInterestingProposal();
+ if (name != null) relevance += computeRelevanceForCaseMatching(name, bindingName);
+ relevance += computeRelevanceForQualification(prefixRequired);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ char [] defaultSignature={'(',')','V'};
+ this.noProposal = false;
+ // Standard proposal
+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setSignature(defaultSignature);
+ proposal.setDeclarationPackageName(packageName);
+ proposal.setName(bindingName);
+ proposal.setCompletion(completion);
+ proposal.setFlags(modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(enclosingTypeNames != null) proposal.setParameterNames(enclosingTypeNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Javadoc proposal
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_METHOD_REF)) {
+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_METHOD_REF, this.actualCompletionPosition);
+ proposal.setName(bindingName);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags( modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ if(enclosingTypeNames != null) proposal.setParameterNames(enclosingTypeNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ }
+
+ }
+ break;
+ case Binding.VARIABLE:
+ case Binding.LOCAL:
+ case Binding.FIELD:
+ {
+ char[] completion = bindingName;
+
+ if (binding2 instanceof LocalVariableBinding && binding2.isValidBinding()) {
+ LocalVariableBinding variableBinding = (LocalVariableBinding) binding2;
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForInterestingProposal(variableBinding);
+ if (name != null) relevance += computeRelevanceForCaseMatching(name, variableBinding.name);
+ relevance += computeRelevanceForExpectingType(variableBinding.type);
+ relevance += computeRelevanceForQualification(prefixRequired);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ this.noProposal = false;
+ // Standard proposal
+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+ if (variableBinding.declaringScope instanceof CompilationUnitScope) {
+ CompilationUnitScope compilationUnitScope = (CompilationUnitScope) variableBinding.declaringScope;
+
+ proposal.setDeclarationSignature(getSignature(compilationUnitScope.referenceContext.compilationUnitBinding));
+ }
+ proposal.setSignature(getSignature(variableBinding.type));
+ proposal.setDeclarationTypeName(packageName);
+ proposal.setPackageName(variableBinding.type.qualifiedPackageName());
+ proposal.setTypeName(variableBinding.type.qualifiedSourceName());
+ proposal.setName(variableBinding.name);
+ proposal.setCompletion(completion);
+ proposal.setFlags(variableBinding.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Javadoc completions
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_FIELD_REF)) {
+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_FIELD_REF, this.actualCompletionPosition);
+ proposal.setSignature(getSignature(variableBinding.type));
+ proposal.setDeclarationPackageName(packageName);
+ proposal.setPackageName(variableBinding.type.qualifiedPackageName());
+ proposal.setTypeName(variableBinding.type.qualifiedSourceName());
+ proposal.setName(variableBinding.name);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags(variableBinding.modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ } else {
+ if (binding2!=null)
+ //TODO: implement
+ throw new UnimplementedException();
+ }
+
+ }
+ break;
+ }
+ }
+ this.acceptedBindings = null; // reset
+ }
+
+
+
+
+ // this code is derived from FunctionBinding#areParametersCompatibleWith(TypeBinding[])
+ private final boolean areParametersCompatibleWith(TypeBinding[] parameters, TypeBinding[] arguments, boolean isVarargs) {
+ int paramLength = parameters.length;
+ int argLength = arguments.length;
+ int lastIndex = argLength;
+ if (isVarargs) {
+ lastIndex = paramLength - 1;
+ if (paramLength == argLength) { // accept X[] but not X or X[][]
+ TypeBinding varArgType = parameters[lastIndex]; // is an ArrayBinding by definition
+ TypeBinding lastArgument = arguments[lastIndex];
+ if (varArgType != lastArgument && !lastArgument.isCompatibleWith(varArgType))
+ return false;
+ } else if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
+ TypeBinding varArgType = ((ArrayBinding) parameters[lastIndex]).elementsType();
+ for (int i = lastIndex; i < argLength; i++)
+ if (varArgType != arguments[i] && !arguments[i].isCompatibleWith(varArgType))
+ return false;
+ } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
+ return false;
+ }
+ // now compare standard arguments from 0 to lastIndex
+ } else {
+ if(paramLength != argLength)
+ return false;
+ }
+ for (int i = 0; i < lastIndex; i++)
+ if (parameters[i] != arguments[i] && !arguments[i].isCompatibleWith(parameters[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * Propose a constructor based on an {@link AcceptedConstructor}.
+ *
+ * @param acceptedConstructor {@link AcceptedConstructor} to create a proposal for
+ */
+ private void proposeConstructor(AcceptedConstructor acceptedConstructor) {
+ proposeConstructor(
+ acceptedConstructor.typeName,
+ acceptedConstructor.parameterCount,
+ acceptedConstructor.parameterTypes,
+ acceptedConstructor.parameterNames,
+ acceptedConstructor.modifiers,
+ acceptedConstructor.accessibility);
+ }
+
+ /**
+ * Create a constructor proposal based on the given information.
+ *
+ * @param typeName Name of the type the constructor is for
+ * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor
+ * @param parameterTypes Type names of the parameters, should be same length as parameterCount
+ * @param parameterNames Type names of the parameters, should be same length as parameterCount
+ * @param modifiers Type names of the parameters, should be same length as parameterCount
+ * @param accessibility Accessibility of the constructor
+ *
+ * @see Flags
+ * @see IAccessRule
+ */
+ private void proposeConstructor(
+ char[] typeName,
+ int parameterCount,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ int modifiers,
+ int accessibility) {
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(accessibility);
+ relevance += computeRelevanceForCaseMatching(this.completionToken, typeName);
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException(typeName);
+
+ char[] completion;
+ if (this.source != null
+ && this.source.length > this.endPosition
+ && this.source[this.endPosition] == '(') {
+ completion = CharOperation.NO_CHAR;
+ } else {
+ completion = new char[] { '(', ')' };
+ }
+
+ //NOTE: currently all constructors are assumed to be public
+ int flags = modifiers;
+ flags |= Flags.AccPublic;
+
+ switch (parameterCount) {
+ case -1: {// default constructor
+ flags = Flags.AccPublic;
+ this.noProposal = false;
+ if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
+ CompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(createNonGenericTypeSignature(typeName));
+ proposal.setDeclarationTypeName(typeName);
+ proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
+ proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
+ proposal.setParameterNames(CharOperation.NO_CHAR_CHAR);
+ proposal.setName(typeName);
+ proposal.setIsContructor(true);
+ proposal.setCompletion(completion);
+ proposal.setFlags(flags);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ }
+ break;
+ }
+ case 0: {// constructor with no parameter
+ this.noProposal = false;
+ if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
+ CompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(createNonGenericTypeSignature(typeName));
+ proposal.setDeclarationTypeName(typeName);
+ proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
+ proposal.setParameterTypeNames(CharOperation.NO_CHAR_CHAR);
+ proposal.setParameterNames(CharOperation.NO_CHAR_CHAR);
+ proposal.setName(typeName);
+ proposal.setIsContructor(true);
+ proposal.setCompletion(completion);
+ proposal.setFlags(flags);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+
+ }
+ break;
+ }
+ default: {// constructor with parameter
+ int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length;
+ if (parameterCount != parameterNamesLength) {
+ parameterNames = null;
+ }
+
+
+ this.noProposal = false;
+ if(!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF)) {
+ CompletionProposal proposal = createProposal(CompletionProposal.CONSTRUCTOR_INVOCATION, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(createNonGenericTypeSignature(typeName));
+ proposal.setDeclarationTypeName(typeName);
+ proposal.setParameterPackageNames(CharOperation.NO_CHAR_CHAR);
+ if(parameterTypes != null) {
+ proposal.setParameterTypeNames(parameterTypes);
+ }
+ if (parameterNames != null) {
+ proposal.setParameterNames(parameterNames);
+ }
+ proposal.setName(typeName);
+ proposal.setIsContructor(true);
+ proposal.setCompletion(completion);
+ proposal.setFlags(flags);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+
+ this.requestor.accept(proposal);
+ }
+ break;
+ }
+ }
+ }
+
+ private void proposeType(char[] packageName, char[] simpleTypeName, int modifiers, int accessibility, char[] typeName, char[] fullyQualifiedName, boolean isQualified, Scope scope) {
+ char[] completionName = fullyQualifiedName;
+ if(isQualified) {
+ if (packageName == null || packageName.length == 0)
+ if (this.unitScope != null && this.unitScope.getDefaultPackage().compoundName != CharOperation.NO_CHAR_CHAR)
+ return; // ignore types from the default package from outside it
+ } else {
+ completionName = simpleTypeName;
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(accessibility);
+ relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName);
+ relevance += computeRelevanceForExpectingType(packageName, simpleTypeName);
+ relevance += computeRelevanceForQualification(isQualified);
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException(simpleTypeName);
+
+ // put proposals that have '_' at the start of their final segment down the list
+ char[] lastSegment = CharOperation.lastSegment(completionName, '.');
+ if(CharOperation.indexOf('_', lastSegment) == 0) {
+ relevance--;
+ }
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance);
+ }
+ }
+
+ /**
+ * One result of the search consists of a new package.
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+ public void acceptPackage(char[] packageName) {
+
+ if (this.knownPkgs.containsKey(packageName)) return;
+
+ this.knownPkgs.put(packageName, this);
+
+// char[] completion;
+// if(this.resolvingImports) {
+// if(this.resolvingStaticImports) {
+// completion = CharOperation.concat(packageName, new char[] { '.' });
+// } else {
+// completion = CharOperation.concat(packageName, new char[] { '.', '*', ';' });
+// }
+// } else {
+// completion = packageName;
+// }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName);
+ if(!this.resolvingImports) {
+ relevance += computeRelevanceForQualification(true);
+ }
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ this.noProposal = false;
+// if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+// CompletionProposal proposal = this.createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition);
+// proposal.setDeclarationSignature(packageName);
+// proposal.setPackageName(packageName);
+// proposal.setCompletion(completion);
+// proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+// proposal.setRelevance(relevance);
+// this.requestor.accept(proposal);
+// if(DEBUG) {
+// this.printDebug(proposal);
+// }
+// }
+ }
+
+ private void buildContext(
+ ASTNode astNode,
+ ASTNode astNodeParent,
+ Binding qualifiedBinding,
+ Scope scope) {
+ CompletionContext context = new CompletionContext();
+
+ // build expected types context
+ if (this.expectedTypesPtr > -1) {
+ int length = this.expectedTypesPtr + 1;
+ char[][] expTypes = new char[length][];
+ char[][] expKeys = new char[length][];
+ for (int i = 0; i < length; i++) {
+ expTypes[i] = getSignature(this.expectedTypes[i]);
+ expKeys[i] = this.expectedTypes[i].computeUniqueKey();
+ }
+ context.setExpectedTypesSignatures(expTypes);
+ context.setExpectedTypesKeys(expKeys);
+ }
+
+ context.setOffset(this.actualCompletionPosition + 1 - this.offset);
+
+ // Set javadoc info
+ if (astNode instanceof CompletionOnJavadoc) {
+ this.assistNodeInJavadoc = ((CompletionOnJavadoc)astNode).getCompletionFlags();
+ context.setJavadoc(this.assistNodeInJavadoc);
+ }
+
+ if (!(astNode instanceof CompletionOnJavadoc)) {
+ CompletionScanner scanner = (CompletionScanner)this.parser.scanner;
+ context.setToken(scanner.completionIdentifier);
+ context.setTokenRange(
+ scanner.completedIdentifierStart - this.offset,
+ scanner.completedIdentifierEnd - this.offset,
+ scanner.endOfEmptyToken - this.offset);
+ } else if(astNode instanceof CompletionOnJavadocTag) {
+ CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode;
+ context.setToken(CharOperation.concat(new char[]{'@'}, javadocTag.token));
+ context.setTokenRange(
+ javadocTag.tagSourceStart - this.offset,
+ javadocTag.tagSourceEnd - this.offset,
+ ((CompletionScanner)this.parser.javadocParser.scanner).endOfEmptyToken - this.offset);
+ } else {
+ CompletionScanner scanner = (CompletionScanner)this.parser.javadocParser.scanner;
+ context.setToken(scanner.completionIdentifier);
+ context.setTokenRange(
+ scanner.completedIdentifierStart - this.offset,
+ scanner.completedIdentifierEnd - this.offset,
+ scanner.endOfEmptyToken - this.offset);
+ }
+
+ if(astNode instanceof CompletionOnStringLiteral) {
+ context.setTokenKind(CompletionContext.TOKEN_KIND_STRING_LITERAL);
+ } else {
+ context.setTokenKind(CompletionContext.TOKEN_KIND_NAME);
+ }
+
+ if(DEBUG) {
+ System.out.println(context.toString());
+ }
+ this.requestor.acceptContext(context);
+ }
+
+ private boolean complete(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope, boolean insideTypeAnnotation) {
+
+ setSourceRange(astNode.sourceStart, astNode.sourceEnd);
+
+ scope = computeForbiddenBindings(astNode, astNodeParent, scope);
+ computeUninterestingBindings(astNodeParent, scope);
+ if(astNodeParent != null) {
+ if(!isValidParent(astNodeParent, astNode, scope)) return false;
+ computeExpectedTypes(astNodeParent, astNode, scope);
+ }
+
+ buildContext(astNode, astNodeParent, qualifiedBinding, scope);
+
+ if (astNode instanceof CompletionOnFieldType) {
+
+ CompletionOnFieldType field = (CompletionOnFieldType) astNode;
+ CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
+ this.completionToken = type.token;
+ setSourceRange(type.sourceStart, type.sourceEnd);
+
+ findTypesAndPackages(this.completionToken, scope, new ObjectVector());
+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ findKeywordsForMember(this.completionToken, field.modifiers);
+ }
+
+ if (!field.isLocalVariable && field.modifiers == ClassFileConstants.AccDefault) {
+ SourceTypeBinding enclosingType = scope.enclosingSourceType();
+
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) {
+ findMethods(this.completionToken,null,null,enclosingType,scope,new ObjectVector(),false,false,true,null,null,false,false,true,null, null, null, false);
+ }
+ if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) {
+ proposeNewMethod(this.completionToken, enclosingType);
+ }
+ }
+ } else if (astNode instanceof CompletionOnSingleNameReference) {
+
+ CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode;
+ this.completionToken = singleNameReference.token;
+ SwitchStatement switchStatement = astNodeParent instanceof SwitchStatement ? (SwitchStatement) astNodeParent : null;
+
+ if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
+ char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, singleNameReference);
+
+ findUnresolvedReference(
+ singleNameReference.sourceStart,
+ singleNameReference.sourceEnd,
+ (BlockScope)scope,
+ alreadyDefinedName);
+ }
+ findVariablesAndMethods(
+ this.completionToken,
+ scope,
+ singleNameReference,
+ scope,
+ insideTypeAnnotation,
+ singleNameReference.isInsideAnnotationAttribute);
+ // can be the start of a qualified type name
+ findTypesAndPackages(this.completionToken, scope, new ObjectVector());
+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ if (this.completionToken != null && this.completionToken.length != 0) {
+ findKeywords(this.completionToken, singleNameReference.possibleKeywords, false, false);
+ } else {
+ findTrueOrFalseKeywords(singleNameReference.possibleKeywords);
+ }
+ }
+ if (singleNameReference.canBeExplicitConstructor && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)){
+ if (CharOperation.prefixEquals(this.completionToken, Keywords.THIS, false)) {
+ ReferenceBinding ref = scope.enclosingSourceType();
+ findExplicitConstructors(Keywords.THIS, ref, (MethodScope)scope, singleNameReference);
+ } else if (CharOperation.prefixEquals(this.completionToken, Keywords.SUPER, false)) {
+ ReferenceBinding ref = scope.enclosingSourceType();
+ findExplicitConstructors(Keywords.SUPER, ref.superclass(), (MethodScope)scope, singleNameReference);
+ }
+ }
+
+ } else if (astNode instanceof CompletionOnSingleTypeReference) {
+
+ CompletionOnSingleTypeReference singleRef = (CompletionOnSingleTypeReference) astNode;
+
+ this.completionToken = singleRef.token;
+
+ this.assistNodeIsClass = singleRef.isClass();
+ this.assistNodeIsException = singleRef.isException();
+ this.assistNodeIsConstructor = singleRef.isConstructorType;
+ this.assistNodeIsSuperType = singleRef.isSuperType();
+
+
+ // can be the start of a qualified type name
+ if (qualifiedBinding == null) {
+ ObjectVector typesFound = new ObjectVector();
+ if (this.assistNodeIsException && astNodeParent instanceof TryStatement) {
+ findExceptionFromTryStatement(
+ this.completionToken,
+ null,
+ scope.enclosingSourceType(),
+ (BlockScope)scope,
+ typesFound);
+ }
+ findTypesAndPackages(this.completionToken, scope, typesFound);
+
+ } else if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ findMemberTypes(
+ this.completionToken,
+ (ReferenceBinding) qualifiedBinding,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ false,
+ false,
+ false,
+ !this.assistNodeIsConstructor,
+ null,
+ new ObjectVector());
+ }
+ } else if (astNode instanceof CompletionOnSingleTypeName) {
+
+ CompletionOnSingleTypeName singleRef = (CompletionOnSingleTypeName) astNode;
+ this.completionToken = singleRef.token;
+
+ this.assistNodeIsClass = true;
+ this.assistNodeIsConstructor = true;
+
+ // can be the start of a qualified type name
+ if (qualifiedBinding == null) {
+ ObjectVector typesFound = new ObjectVector();
+ findTypesAndPackages(this.completionToken, scope, typesFound);
+ } else if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ findMemberTypes(
+ this.completionToken,
+ (ReferenceBinding) qualifiedBinding,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ false,
+ false,
+ false,
+ !this.assistNodeIsConstructor,
+ null,
+ new ObjectVector());
+ }
+ }
+ else if (astNode instanceof CompletionOnQualifiedNameReference) {
+
+ this.insideQualifiedReference = true;
+ CompletionOnQualifiedNameReference ref =
+ (CompletionOnQualifiedNameReference) astNode;
+ this.completionToken = ref.completionIdentifier;
+ long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
+
+ if (qualifiedBinding.problemId() == ProblemReasons.NotFound) {
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ // complete field members with missing fields type
+ // class X {
+ // Missing f;
+ // void foo() {
+ // f.|
+ // }
+ // }
+ if (this.assistNodeInJavadoc == 0 &&
+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) ||
+ this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) {
+ if(ref.tokens.length == 1) {
+ findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation);
+ }
+ }
+ } else if (qualifiedBinding instanceof VariableBinding) {
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
+ if (receiverType != null) {
+ findFieldsAndMethods(this.completionToken, receiverType, scope, ref, scope,false,false,false, null, null, null, false);
+ } else if (this.assistNodeInJavadoc == 0 &&
+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) ||
+ this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) {
+ boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF);
+ boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF);
+ if (proposeField || proposeMethod) {
+ if (qualifiedBinding instanceof LocalVariableBinding) {
+ // complete local variable members with missing variables type
+ // class X {
+ // void foo() {
+ // Missing f;
+ // f.|
+ // }
+ // }
+ LocalVariableBinding localVariableBinding = (LocalVariableBinding) qualifiedBinding;
+
+ findFieldsAndMethodsFromMissingType(
+ this.completionToken,
+ localVariableBinding.declaration.type,
+ localVariableBinding.declaringScope,
+ ref,
+ scope);
+ }
+ }
+ }
+
+ } else if (qualifiedBinding instanceof ReferenceBinding) {
+ boolean isInsideAnnotationAttribute = ref.isInsideAnnotationAttribute;
+ ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+
+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ findMemberTypes(
+ this.completionToken,
+ receiverType,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ true,
+ new ObjectVector());
+ }
+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+ findClassField(this.completionToken, (TypeBinding) qualifiedBinding, scope);
+ }
+
+ MethodScope methodScope = null;
+ if (!isInsideAnnotationAttribute &&
+ !this.requestor.isIgnored(CompletionProposal.KEYWORD) &&
+ ((scope instanceof MethodScope && !((MethodScope)scope).isStatic)
+ || ((methodScope = scope.enclosingMethodScope()) != null && !methodScope.isStatic))) {
+ if (this.completionToken.length > 0) {
+ findKeywords(this.completionToken, new char[][]{Keywords.THIS}, false, true);
+ } else {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.THIS);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords
+ relevance += R_NON_INHERITED;
+
+ this.noProposal = false;
+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
+ proposal.setName(Keywords.THIS);
+ proposal.setCompletion(Keywords.THIS);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if (DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+
+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+ findFields(
+ this.completionToken,
+ receiverType,
+ scope,
+ new ObjectVector(),
+ new ObjectVector(),
+ true,
+ ref,
+ scope,
+ false,
+ false,
+ null,
+ null,
+ null,
+ false);
+ }
+
+ if (!isInsideAnnotationAttribute && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ findMethods(
+ this.completionToken,
+ null,
+ null,
+ receiverType,
+ scope,
+ new ObjectVector(),
+ true,
+ false,
+ false,
+ ref,
+ scope,
+ false,
+ false,
+ false,
+ null,
+ null,
+ null,
+ false);
+ }
+
+ } else if (qualifiedBinding instanceof PackageBinding) {
+
+ setSourceRange(astNode.sourceStart, (int) completionPosition);
+ // replace to the end of the completion identifier
+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
+ }
+ } else if (astNode instanceof CompletionOnQualifiedTypeReference) {
+
+ this.insideQualifiedReference = true;
+
+ CompletionOnQualifiedTypeReference ref =
+ (CompletionOnQualifiedTypeReference) astNode;
+
+ this.assistNodeIsClass = ref.isClass();
+ this.assistNodeIsException = ref.isException();
+ this.assistNodeIsSuperType = ref.isSuperType();
+
+ this.completionToken = ref.completionIdentifier;
+ long completionPosition = ref.sourcePositions[ref.tokens.length];
+
+ // get the source positions of the completion identifier
+ if (qualifiedBinding instanceof ReferenceBinding) {
+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+
+ ObjectVector typesFound = new ObjectVector();
+
+ if (this.assistNodeIsException && astNodeParent instanceof TryStatement) {
+ findExceptionFromTryStatement(
+ this.completionToken,
+ (ReferenceBinding)qualifiedBinding,
+ scope.enclosingSourceType(),
+ (BlockScope)scope,
+ typesFound);
+ }
+
+ findMemberTypes(
+ this.completionToken,
+ (ReferenceBinding) qualifiedBinding,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ false,
+ typesFound);
+ }
+ } else if (qualifiedBinding instanceof PackageBinding) {
+
+ setSourceRange(astNode.sourceStart, (int) completionPosition);
+ // replace to the end of the completion identifier
+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
+ }
+ } else if (astNode instanceof CompletionOnQualifiedType) {
+
+ this.insideQualifiedReference = true;
+
+ CompletionOnQualifiedType ref =
+ (CompletionOnQualifiedType) astNode;
+
+ this.assistNodeIsClass = true;
+
+ this.completionToken = ref.completionIdentifier;
+ long completionPosition = ref.sourcePositions[ref.tokens.length];
+
+ // get the source positions of the completion identifier
+ if (qualifiedBinding instanceof ReferenceBinding) {
+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+
+ ObjectVector typesFound = new ObjectVector();
+
+
+ findMemberTypes(
+ this.completionToken,
+ (ReferenceBinding) qualifiedBinding,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ false,
+ typesFound);
+ }
+ }
+ } else if (astNode instanceof CompletionOnMemberAccess) {
+ this.insideQualifiedReference = true;
+ CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
+ long completionPosition = access.nameSourcePosition;
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+
+
+
+// this.assistNodeIsClass = true;
+// this.assistNodeIsConstructor = true;
+
+ // can be the start of a qualified type name
+ if (qualifiedBinding == null) {
+
+ this.completionToken = computeToken(access);
+ setSourceRange((int) (completionPosition >>> 32) - (this.completionToken.length - access.token.length), (int) completionPosition);
+
+ ObjectVector typesFound = new ObjectVector();
+ findTypesAndPackages(this.completionToken, scope, typesFound);
+ } else {
+ this.completionToken = access.token;
+ if (qualifiedBinding.problemId() == ProblemReasons.NotFound) {
+ // complete method members with missing return type
+ // class X {
+ // Missing f() {return null;}
+ // void foo() {
+ // f().|
+ // }
+ // }
+ if (this.assistNodeInJavadoc == 0 &&
+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) ||
+ this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) {
+ ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) qualifiedBinding;
+ findFieldsAndMethodsFromMissingReturnType(
+ problemMethodBinding.selector,
+ problemMethodBinding.parameters,
+ scope,
+ access,
+ insideTypeAnnotation);
+ }
+ } else {
+ if (!access.isInsideAnnotation) {
+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ findKeywords(this.completionToken, new char[][]{Keywords.NEW}, false, false);
+ }
+
+ findFieldsAndMethods(
+ this.completionToken,
+ ((TypeBinding) qualifiedBinding),
+ scope,
+ access,
+ scope,
+ access.isStatic,
+ false,
+ access.receiver instanceof SuperReference,
+ null,
+ null,
+ null,
+ false);
+ // reset completion token to find types
+ this.completionToken = computeToken(access);
+ setSourceRange((int) (completionPosition >>> 32) - (this.completionToken.length - access.token.length), (int) completionPosition);
+ findTypesAndPackages(this.completionToken, scope, new ObjectVector());
+ // after looking for types set the completion token back to original value
+ this.completionToken = access.token;
+ setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+ if (qualifiedBinding instanceof FunctionTypeBinding) {
+ FunctionTypeBinding functionTypeBinding = (FunctionTypeBinding) qualifiedBinding;
+ if (functionTypeBinding.functionBinding!=null && functionTypeBinding.functionBinding.isConstructor())
+ {
+ ReferenceBinding declaringClass = (ReferenceBinding)functionTypeBinding.functionBinding.returnType;
+ findFieldsAndMethods(
+ this.completionToken,
+ declaringClass,
+ scope,
+ access,
+ scope,
+ true,
+ false,
+ access.receiver instanceof SuperReference,
+ null,
+ null,
+ null,
+ false);
+
+ }
+
+ }
+ }
+ }
+ }
+
+ } else if (astNode instanceof CompletionOnMessageSend) {
+ setSourceRange(astNode.sourceStart, astNode.sourceEnd, false);
+
+ CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
+ TypeBinding[] argTypes = computeTypes(messageSend.arguments);
+ this.completionToken = messageSend.selector;
+ if (qualifiedBinding == null) {
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope);
+ }
+ } else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ findMethods(
+ this.completionToken,
+ null,
+ argTypes,
+ (messageSend.receiver!=null)?
+ (ReferenceBinding)((ReferenceBinding) qualifiedBinding)
+ :null,
+ scope,
+ new ObjectVector(),
+ false,
+ false,
+ false,
+ messageSend,
+ scope,
+ false,
+ messageSend.receiver instanceof SuperReference,
+ false,
+ null,
+ null,
+ null,
+ false);
+ }
+ } else if (astNode instanceof CompletionOnExplicitConstructorCall) {
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ setSourceRange(astNode.sourceStart, astNode.sourceEnd, false);
+
+ CompletionOnExplicitConstructorCall constructorCall =
+ (CompletionOnExplicitConstructorCall) astNode;
+ TypeBinding[] argTypes = computeTypes(constructorCall.arguments);
+ findConstructors(
+ (ReferenceBinding) qualifiedBinding,
+ argTypes,
+ scope,
+ constructorCall,
+ false);
+ }
+ } else if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
+ setSourceRange(astNode.sourceStart, astNode.sourceEnd, false);
+
+ CompletionOnQualifiedAllocationExpression allocExpression =
+ (CompletionOnQualifiedAllocationExpression) astNode;
+ TypeBinding[] argTypes = computeTypes(allocExpression.arguments);
+
+ ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)
+ && ref.isClass()) {
+ findConstructors(
+ ref,
+ argTypes,
+ scope,
+ allocExpression,
+ false);
+ }
+ if (!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)){
+ findAnonymousType(
+ ref,
+ argTypes,
+ scope,
+ allocExpression);
+ }
+ } else if (astNode instanceof CompletionOnClassLiteralAccess) {
+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+ CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
+ setSourceRange(access.classStart, access.sourceEnd);
+
+ this.completionToken = access.completionIdentifier;
+
+ findClassField(this.completionToken, (TypeBinding) qualifiedBinding, scope);
+ }
+ } else if (astNode instanceof CompletionOnMethodName) {
+ if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
+ CompletionOnMethodName method = (CompletionOnMethodName) astNode;
+
+ setSourceRange(method.sourceStart, method.selectorEnd);
+
+ FieldBinding[] fields = scope.enclosingSourceType().fields();
+ char[][] excludeNames = new char[fields.length][];
+ for(int i = 0 ; i < fields.length ; i++){
+ excludeNames[i] = fields[i].name;
+ }
+
+ this.completionToken = method.selector;
+
+ findVariableNames(this.completionToken, method.returnType, excludeNames, null, FIELD, method.modifiers);
+ }
+ } else if (astNode instanceof CompletionOnFieldName) {
+ if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
+ CompletionOnFieldName field = (CompletionOnFieldName) astNode;
+
+ FieldBinding[] fields = scope.enclosingSourceType().fields();
+ char[][] excludeNames = new char[fields.length][];
+ for(int i = 0 ; i < fields.length ; i++){
+ excludeNames[i] = fields[i].name;
+ }
+
+ this.completionToken = field.realName;
+
+ findVariableNames(field.realName, field.type, excludeNames, null, FIELD, field.modifiers);
+ }
+ } else if (astNode instanceof CompletionOnLocalName || astNode instanceof CompletionOnArgumentName) {
+ if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
+ LocalDeclaration variable = (LocalDeclaration) astNode;
+
+ int kind;
+ if (variable instanceof CompletionOnLocalName){
+ this.completionToken = ((CompletionOnLocalName) variable).realName;
+ kind = LOCAL;
+ } else {
+ CompletionOnArgumentName arg = (CompletionOnArgumentName) variable;
+ this.completionToken = arg.realName;
+ kind = arg.isCatchArgument ? LOCAL : ARGUMENT;
+ }
+
+ char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, variable);
+
+ char[][] forbiddenNames = findVariableFromUnresolvedReference(variable, (BlockScope)scope, alreadyDefinedName);
+
+ LocalVariableBinding[] locals = ((BlockScope)scope).locals;
+ char[][] discouragedNames = new char[locals.length][];
+ int localCount = 0;
+ for(int i = 0 ; i < locals.length ; i++){
+ if (locals[i] != null) {
+ discouragedNames[localCount++] = locals[i].name;
+ }
+ }
+
+ System.arraycopy(discouragedNames, 0, discouragedNames = new char[localCount][], 0, localCount);
+
+ findVariableNames(this.completionToken, variable.type, discouragedNames, forbiddenNames, kind, variable.modifiers);
+ }
+ } else if (astNode instanceof CompletionOnKeyword) {
+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ CompletionOnKeyword keyword = (CompletionOnKeyword)astNode;
+ findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), keyword.canCompleteEmptyToken(), false);
+ }
+ } else if(astNode instanceof CompletionOnBrankStatementLabel) {
+ if (!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) {
+ CompletionOnBrankStatementLabel label = (CompletionOnBrankStatementLabel) astNode;
+
+ this.completionToken = label.label;
+
+ this.findLabels(this.completionToken, label.possibleLabels);
+ }
+ } else if(astNode instanceof CompletionOnMessageSendName) {
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ CompletionOnMessageSendName messageSend = (CompletionOnMessageSendName) astNode;
+
+ this.insideQualifiedReference = true;
+ this.completionToken = messageSend.selector;
+ boolean onlyStatic = false;
+ TypeBinding receiverType = null;
+ if(qualifiedBinding instanceof VariableBinding) {
+ receiverType = ((VariableBinding)qualifiedBinding).type;
+ } else if(qualifiedBinding instanceof MethodBinding) {
+ receiverType = ((MethodBinding)qualifiedBinding).returnType;
+ } else if(qualifiedBinding instanceof ReferenceBinding) {
+ onlyStatic = true;
+ receiverType = (TypeBinding)qualifiedBinding;
+ }
+ }
+ // Completion on Javadoc nodes
+ } else if ((astNode.bits & ASTNode.InsideJavadoc) != 0) {
+ if (astNode instanceof CompletionOnJavadocSingleTypeReference) {
+
+ CompletionOnJavadocSingleTypeReference typeRef = (CompletionOnJavadocSingleTypeReference) astNode;
+ this.completionToken = typeRef.token;
+ this.javadocTagPosition = typeRef.tagSourceStart;
+ setSourceRange(typeRef.sourceStart, typeRef.sourceEnd);
+ findTypesAndPackages(this.completionToken, scope, new ObjectVector());
+
+ } else if (astNode instanceof CompletionOnJavadocQualifiedTypeReference) {
+
+ this.insideQualifiedReference = true;
+
+ CompletionOnJavadocQualifiedTypeReference typeRef = (CompletionOnJavadocQualifiedTypeReference) astNode;
+ this.completionToken = typeRef.completionIdentifier;
+ long completionPosition = typeRef.sourcePositions[typeRef.tokens.length];
+ this.javadocTagPosition = typeRef.tagSourceStart;
+
+ // get the source positions of the completion identifier
+ if (qualifiedBinding instanceof ReferenceBinding) {
+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF) ||
+ ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_TYPE_REF))) {
+ int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32);
+ setSourceRange(rangeStart, (int) completionPosition);
+ findMemberTypes(this.completionToken,
+ (ReferenceBinding) qualifiedBinding,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ false,
+ new ObjectVector());
+ }
+ } else if (qualifiedBinding instanceof PackageBinding) {
+
+ setSourceRange(astNode.sourceStart, (int) completionPosition);
+ // replace to the end of the completion identifier
+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope);
+ }
+ } else if (astNode instanceof CompletionOnJavadocFieldReference) {
+
+ this.insideQualifiedReference = true;
+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) astNode;
+ this.completionToken = fieldRef.token;
+ long completionPosition = fieldRef.nameSourcePosition;
+ this.javadocTagPosition = fieldRef.tagSourceStart;
+
+ if (fieldRef.receiverType != null && fieldRef.receiverType.isValidBinding()) {
+ ReferenceBinding receiverType = (ReferenceBinding) fieldRef.receiverType;
+ int rangeStart = (int) (completionPosition >>> 32);
+ if (fieldRef.receiver.isThis()) {
+ if (fieldRef.completeInText()) {
+ rangeStart = fieldRef.separatorPosition;
+ }
+ } else if (fieldRef.completeInText()) {
+ rangeStart = fieldRef.receiver.sourceStart;
+ }
+ setSourceRange(rangeStart, (int) completionPosition);
+
+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)
+ || !this.requestor.isIgnored(CompletionProposal.JSDOC_FIELD_REF)) {
+ findFields(this.completionToken,
+ receiverType,
+ scope,
+ new ObjectVector(),
+ new ObjectVector(),
+ false, /*not only static */
+ fieldRef,
+ scope,
+ false,
+ true,
+ null,
+ null,
+ null,
+ false);
+ }
+
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)
+ || !this.requestor.isIgnored(CompletionProposal.JSDOC_METHOD_REF)) {
+ findMethods(this.completionToken,
+ null,
+ null,
+ receiverType,
+ scope,
+ new ObjectVector(),
+ false, /*not only static */
+ false,
+ false,
+ fieldRef,
+ scope,
+ false,
+ false,
+ true,
+ null,
+ null,
+ null,
+ false);
+ if (fieldRef.receiverType instanceof ReferenceBinding) {
+ ReferenceBinding refBinding = (ReferenceBinding)fieldRef.receiverType;
+ if (this.completionToken == null
+ || CharOperation.prefixEquals(this.completionToken, refBinding.sourceName)
+ || (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {
+ findConstructors(refBinding, null, scope, fieldRef, false);
+ }
+ }
+ }
+ }
+ } else if (astNode instanceof CompletionOnJavadocMessageSend) {
+
+ CompletionOnJavadocMessageSend messageSend = (CompletionOnJavadocMessageSend) astNode;
+ TypeBinding[] argTypes = null; //computeTypes(messageSend.arguments);
+ this.completionToken = messageSend.selector;
+ this.javadocTagPosition = messageSend.tagSourceStart;
+
+ // Set source range
+ int rangeStart = astNode.sourceStart;
+ if (messageSend.receiver!=null && messageSend.receiver.isThis()) {
+ if (messageSend.completeInText()) {
+ rangeStart = messageSend.separatorPosition;
+ }
+ } else if (messageSend.completeInText()) {
+ rangeStart = messageSend.receiver.sourceStart;
+ }
+ setSourceRange(rangeStart, astNode.sourceEnd, false);
+
+ if (qualifiedBinding == null) {
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope);
+ }
+ } else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ findMethods(
+ this.completionToken,
+ null,
+ argTypes,
+ ((ReferenceBinding) qualifiedBinding),
+ scope,
+ new ObjectVector(),
+ false,
+ false/* prefix match */,
+ false,
+ messageSend,
+ scope,
+ false,
+ messageSend.receiver instanceof SuperReference,
+ true,
+ null,
+ null,
+ null,
+ false);
+ }
+ } else if (astNode instanceof CompletionOnJavadocAllocationExpression) {
+// setSourceRange(astNode.sourceStart, astNode.sourceEnd, false);
+
+ CompletionOnJavadocAllocationExpression allocExpression = (CompletionOnJavadocAllocationExpression) astNode;
+ this.javadocTagPosition = allocExpression.tagSourceStart;
+ int rangeStart = astNode.sourceStart;
+ if (allocExpression.type.isThis()) {
+ if (allocExpression.completeInText()) {
+ rangeStart = allocExpression.separatorPosition;
+ }
+ } else if (allocExpression.completeInText()) {
+ rangeStart = allocExpression.type.sourceStart;
+ }
+ setSourceRange(rangeStart, astNode.sourceEnd, false);
+ TypeBinding[] argTypes = computeTypes(allocExpression.arguments);
+
+ ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && ref.isClass()) {
+ findConstructors(ref, argTypes, scope, allocExpression, false);
+ }
+ } else if (astNode instanceof CompletionOnJavadocParamNameReference) {
+ if (!this.requestor.isIgnored(CompletionProposal.JSDOC_PARAM_REF)) {
+ CompletionOnJavadocParamNameReference paramRef = (CompletionOnJavadocParamNameReference) astNode;
+ setSourceRange(paramRef.tagSourceStart, paramRef.tagSourceEnd);
+ findJavadocParamNames(paramRef.token, paramRef.missingParams, false);
+ }
+ } else if (astNode instanceof CompletionOnJavadocTag) {
+ CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode;
+ setSourceRange(javadocTag.tagSourceStart, javadocTag.sourceEnd);
+ findJavadocBlockTags(javadocTag);
+ findJavadocInlineTags(javadocTag);
+ }
+ }
+ return true;
+ }
+
+ public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
+ if(this.requestor != null){
+ this.requestor.beginReporting();
+ }
+ boolean contextAccepted = false;
+ IType topLevelType = type;
+ while(topLevelType.getDeclaringType() != null) {
+ topLevelType = topLevelType.getDeclaringType();
+ }
+
+ this.fileName = topLevelType.getParent().getElementName().toCharArray();
+ CompilationResult compilationResult = new CompilationResult(this.fileName, this.packageName, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+
+ CompilationUnitDeclaration compilationUnit = null;
+
+ try {
+ // TypeConverter is used instead of SourceTypeConverter because the type
+ // to convert can be a binary type or a source type
+ TypeDeclaration typeDeclaration = null;
+ if (type instanceof SourceType) {
+ SourceType sourceType = (SourceType) type;
+ ISourceType info = (ISourceType) sourceType.getElementInfo();
+ compilationUnit = SourceTypeConverter.buildCompilationUnit(
+ new ISourceType[] {info},//sourceTypes[0] is always toplevel here
+ SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+ | SourceTypeConverter.MEMBER_TYPE, // need member types
+ // no need for field initialization
+ this.problemReporter,
+ compilationResult);
+ if (compilationUnit.types != null)
+ typeDeclaration = compilationUnit.types[0];
+ } else {
+ compilationUnit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
+ typeDeclaration = BinaryTypeConverter.buildTypeDeclaration(type, compilationUnit, compilationResult);
+ }
+
+ if(typeDeclaration != null) {
+ // build AST from snippet
+ Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
+
+ // merge AST
+ FieldDeclaration[] oldFields = typeDeclaration.fields;
+ FieldDeclaration[] newFields = null;
+ if (oldFields != null) {
+ newFields = new FieldDeclaration[oldFields.length + 1];
+ System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
+ newFields[oldFields.length] = fakeInitializer;
+ } else {
+ newFields = new FieldDeclaration[] {fakeInitializer};
+ }
+ typeDeclaration.fields = newFields;
+
+ if(DEBUG) {
+ System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$
+ System.out.println(compilationUnit.toString());
+ }
+
+ if (compilationUnit.types != null) {
+ try {
+ this.lookupEnvironment.buildTypeBindings(compilationUnit, null /*no access restriction*/);
+
+ if ((this.unitScope = compilationUnit.scope) != null) {
+ this.lookupEnvironment.completeTypeBindings(compilationUnit, true);
+ compilationUnit.scope.faultInTypes();
+ compilationUnit.resolve();
+ }
+ } catch (CompletionNodeFound e) {
+ // completionNodeFound = true;
+ if (e.astNode != null) {
+ // if null then we found a problem in the completion node
+ contextAccepted = complete(e.astNode, this.parser.assistNodeParent, e.qualifiedBinding, e.scope, e.insideTypeAnnotation);
+ }
+ }
+ }
+ if(this.noProposal && this.problem != null) {
+ if(!contextAccepted) {
+ contextAccepted = true;
+ this.requestor.acceptContext(new CompletionContext());
+ }
+ this.requestor.completionFailure(this.problem);
+ if(DEBUG) {
+ this.printDebug(this.problem);
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D (added with fix of 99629)
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (InvalidCursorLocation e) { // may eventually report a usefull error (added to fix 99629)
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object (added with fix of 99629)
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (CompletionNodeFound e){ // internal failure - bugs 5618 (added with fix of 99629)
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch(JavaScriptModelException e) {
+ // Do nothing
+ }
+ if(!contextAccepted) {
+ contextAccepted = true;
+ this.requestor.acceptContext(new CompletionContext());
+ }
+ if(this.requestor != null){
+ this.requestor.endReporting();
+ }
+ }
+
+ private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
+ StringBuffer prefix = new StringBuffer();
+ prefix.append("public class FakeType {\n "); //$NON-NLS-1$
+ if(isStatic) {
+ prefix.append("static "); //$NON-NLS-1$
+ }
+ prefix.append("{\n"); //$NON-NLS-1$
+ for (int i = 0; i < localVariableTypeNames.length; i++) {
+ ASTNode.printModifiers(localVariableModifiers[i], prefix);
+ prefix.append(' ');
+ prefix.append(localVariableTypeNames[i]);
+ prefix.append(' ');
+ prefix.append(localVariableNames[i]);
+ prefix.append(';');
+ }
+
+ char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$
+ this.offset = prefix.length();
+
+ String encoding = this.compilerOptions.defaultEncoding;
+ BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
+ fakeSource,
+ null,
+ "FakeType.java", //$NON-NLS-1$
+ encoding);
+
+ this.actualCompletionPosition = prefix.length() + position - 1;
+
+ CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration fakeAST = this.parser.dietParse(fakeUnit, fakeResult, this.actualCompletionPosition);
+
+ parseBlockStatements(fakeAST, this.actualCompletionPosition);
+
+ return (Initializer)fakeAST.types[0].fields[0];
+ }
+
+ /**
+ * Ask the engine to compute a completion at the specified position
+ * of the given compilation unit.
+ *
+ * No return
+ * completion results are answered through a requestor.
+ *
+ * @param sourceUnit org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit
+ * the source of the current compilation unit.
+ *
+ * @param completionPosition int
+ * a position in the source where the completion is taking place.
+ * This position is relative to the source provided.
+ */
+ public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos) {
+
+ if(DEBUG) {
+ System.out.print("COMPLETION IN "); //$NON-NLS-1$
+ System.out.print(sourceUnit.getFileName());
+ System.out.print(" AT POSITION "); //$NON-NLS-1$
+ System.out.println(completionPosition);
+ System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
+ System.out.println(sourceUnit.getContents());
+ }
+ this.requestor.beginReporting();
+ boolean contextAccepted = false;
+ try {
+ this.fileName = sourceUnit.getFileName();
+ this.packageName= CharOperation.NO_CHAR_CHAR;
+ this.actualCompletionPosition = completionPosition - 1;
+ this.offset = pos;
+ // for now until we can change the UI.
+ CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit = this.parser.dietParse(sourceUnit, result, this.actualCompletionPosition);
+ // boolean completionNodeFound = false;
+ if (parsedUnit != null) {
+ if(DEBUG) {
+ System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+
+ this.parser.inferTypes(parsedUnit, this.compilerOptions);
+
+ ImportReference[] imports = parsedUnit.imports;
+ if (imports != null) {
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportReference importReference = imports[i];
+ if (importReference instanceof CompletionOnImportReference) {
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ contextAccepted = true;
+ this.buildContext(importReference, null, null, null);
+
+ setSourceRange(
+ importReference.sourceStart,
+ importReference.declarationSourceEnd);
+
+ char[][] oldTokens = importReference.tokens;
+ int tokenCount = oldTokens.length;
+ if (tokenCount == 1) {
+ findImports((CompletionOnImportReference)importReference, true);
+ } else if(tokenCount > 1){
+ this.insideQualifiedReference = true;
+
+ char[] lastToken = oldTokens[tokenCount - 1];
+ char[][] qualifierTokens = CharOperation.subarray(oldTokens, 0, tokenCount - 1);
+
+ Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens);
+ if(binding != null) {
+ if(binding instanceof PackageBinding) {
+ findImports((CompletionOnImportReference)importReference, false);
+ } else {
+ ReferenceBinding ref = (ReferenceBinding) binding;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ this.findImportsOfMemberTypes(lastToken, ref);
+ }
+ }
+ }
+ }
+
+ if(this.noProposal && this.problem != null) {
+ this.requestor.completionFailure(this.problem);
+ if(DEBUG) {
+ this.printDebug(this.problem);
+ }
+ }
+ }
+ return;
+ } else if(importReference instanceof CompletionOnKeyword) {
+ contextAccepted = true;
+ this.buildContext(importReference, null, null, null);
+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ setSourceRange(importReference.sourceStart, importReference.sourceEnd);
+ CompletionOnKeyword keyword = (CompletionOnKeyword)importReference;
+ findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, false);
+ }
+ if(this.noProposal && this.problem != null) {
+ this.requestor.completionFailure(this.problem);
+ if(DEBUG) {
+ this.printDebug(this.problem);
+ }
+ }
+ return;
+ }
+ }
+ }
+
+ if (parsedUnit.statements != null) {
+ try {
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ this.source = sourceUnit.getContents();
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+ parsedUnit.scope.faultInTypes();
+ if (Parser.DO_DIET_PARSE)
+ parseBlockStatements(parsedUnit, this.actualCompletionPosition);
+ if(DEBUG) {
+ System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+ parsedUnit.resolve();
+ }
+ } catch (CompletionNodeFound e) {
+ // completionNodeFound = true;
+ if (e.astNode != null) {
+ if(DEBUG) {
+ System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
+ System.out.println(e.astNode.toString());
+ if(this.parser.assistNodeParent != null) {
+ System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$
+ System.out.println(this.parser.assistNodeParent);
+ }
+ }
+ // if null then we found a problem in the completion node
+ contextAccepted = complete(e.astNode, this.parser.assistNodeParent, e.qualifiedBinding, e.scope, e.insideTypeAnnotation);
+ }
+ }
+ }
+ parsedUnit.cleanUp();
+ }
+
+ if(this.noProposal && this.problem != null) {
+ if(!contextAccepted) {
+ contextAccepted = true;
+ CompletionContext context = new CompletionContext();
+ context.setOffset(completionPosition - this.offset);
+ context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
+ this.requestor.acceptContext(context);
+ }
+ this.requestor.completionFailure(this.problem);
+ if(DEBUG) {
+ this.printDebug(this.problem);
+ }
+ }
+ /* Ignore package, import, class & interface keywords for now...
+ if (!completionNodeFound) {
+ if (parsedUnit == null || parsedUnit.types == null) {
+ // this is not good enough... can still be trying to define a second type
+ CompletionScanner scanner = (CompletionScanner) this.parser.scanner;
+ setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd);
+ findKeywords(scanner.completionIdentifier, mainDeclarations, null);
+ }
+ // currently have no way to know if extends/implements are possible keywords
+ }
+ */
+ } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (InvalidCursorLocation e) { // may eventually report a usefull error
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (CompletionNodeFound e){ // internal failure - bugs 5618
+ if(DEBUG) {
+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } finally {
+ this.parser=null;
+ reset();
+ if(!contextAccepted) {
+ contextAccepted = true;
+ CompletionContext context = new CompletionContext();
+ context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
+ context.setOffset(completionPosition - this.offset);
+ this.requestor.acceptContext(context);
+ }
+ this.requestor.endReporting();
+ }
+ }
+
+ private TypeBinding[] computeTypes(Expression[] arguments) {
+ if (arguments == null) return null;
+ int argsLength = arguments.length;
+ TypeBinding[] argTypes = new TypeBinding[argsLength];
+ for (int a = argsLength; --a >= 0;) {
+ argTypes[a] = arguments[a].resolvedType;
+ }
+ return argTypes;
+ }
+
+ private void findAnonymousType(
+ ReferenceBinding currentType,
+ TypeBinding[] argTypes,
+ Scope scope,
+ InvocationSite invocationSite) {
+
+ findConstructors(
+ currentType,
+ argTypes,
+ scope,
+ invocationSite,
+ true);
+ }
+
+ private void findClassField(char[] token, TypeBinding receiverType, Scope scope) {
+
+ if (token == null) return;
+
+ if (token.length <= classField.length
+ && CharOperation.prefixEquals(token, classField, false /* ignore case */
+ )) {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(token, classField);
+ relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); //no access restriction for class field
+ relevance += R_NON_INHERITED;
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+ //proposal.setDeclarationSignature(null);
+ char[] signature =
+ createNonGenericTypeSignature(CLASS);
+ if (this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4) {
+ // add type argument
+ char[] typeArgument = getTypeSignature(receiverType);
+ int oldLength = signature.length;
+ int argumentLength = typeArgument.length;
+ int newLength = oldLength + argumentLength + 2;
+ System.arraycopy(signature, 0, signature = new char[newLength], 0, oldLength - 1);
+ signature[oldLength - 1] = '<';
+ System.arraycopy(typeArgument, 0, signature, oldLength , argumentLength);
+ signature[newLength - 2] = '>';
+ signature[newLength - 1] = ';';
+ }
+ proposal.setSignature(signature);
+ //proposal.setDeclarationPackageName(null);
+ //proposal.setDeclarationTypeName(null);
+ proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.'));
+ proposal.setTypeName(CLASS);
+ proposal.setName(classField);
+ proposal.setCompletion(classField);
+ proposal.setFlags(Flags.AccStatic | Flags.AccPublic);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+
+ private void findExceptionFromTryStatement(
+ char[] typeName,
+ ReferenceBinding exceptionType,
+ ReferenceBinding receiverType,
+ SourceTypeBinding invocationType,
+ BlockScope scope,
+ ObjectVector typesFound,
+ boolean searchSuperClasses) {
+
+
+ if (searchSuperClasses) {
+ ReferenceBinding javaLangThrowable = scope.getJavaLangThrowable();
+ if (exceptionType != javaLangThrowable) {
+ ReferenceBinding superClass = exceptionType.superclass();
+ while(superClass != null && superClass != javaLangThrowable) {
+ findExceptionFromTryStatement(typeName, superClass, receiverType, invocationType, scope, typesFound, false);
+ superClass = superClass.superclass();
+ }
+ }
+ }
+
+ if (typeName.length > exceptionType.sourceName.length)
+ return;
+
+ if (!CharOperation.prefixEquals(typeName, exceptionType.sourceName, false/* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, exceptionType.sourceName)))
+ return;
+
+ if (this.options.checkDeprecation &&
+ exceptionType.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(exceptionType))
+ return;
+
+ if (this.options.checkVisibility) {
+ if (invocationType != null) {
+ if (receiverType != null) {
+ if (!exceptionType.canBeSeenBy(receiverType, invocationType)) return;
+ } else {
+ if (!exceptionType.canBeSeenBy(exceptionType, invocationType)) return;
+ }
+ } else if(!exceptionType.canBeSeenBy(this.unitScope.getDefaultPackage())) {
+ return;
+ }
+ }
+
+ for (int j = typesFound.size; --j >= 0;) {
+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j);
+
+ if (exceptionType == otherType)
+ return;
+
+ if (CharOperation.equals(exceptionType.sourceName, otherType.sourceName, true)) {
+
+ if (exceptionType.enclosingType().isSuperclassOf(otherType.enclosingType()))
+ return;
+
+ }
+ }
+
+ typesFound.add(exceptionType);
+
+ char[] completionName = exceptionType.sourceName();
+
+ boolean isQualified = false;
+
+ if(!this.insideQualifiedReference) {
+ isQualified = true;
+
+ char[] memberPackageName = exceptionType.qualifiedPackageName();
+ char[] memberTypeName = exceptionType.sourceName();
+ char[] memberEnclosingTypeNames = null;
+
+ ReferenceBinding enclosingType = exceptionType.enclosingType();
+ if (enclosingType != null) {
+ memberEnclosingTypeNames = exceptionType.enclosingType().qualifiedSourceName();
+ }
+
+ Scope currentScope = scope;
+ done : while (currentScope != null) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (currentScope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ case Scope.BLOCK_SCOPE :
+ BlockScope blockScope = (BlockScope) currentScope;
+
+ for (int j = 0, length = blockScope.subscopeCount; j < length; j++) {
+
+ if (blockScope.subscopes[j] instanceof ClassScope) {
+ SourceTypeBinding localType =
+ ((ClassScope) blockScope.subscopes[j]).referenceContext.binding;
+
+ if (localType == exceptionType) {
+ isQualified = false;
+ break done;
+ }
+ }
+ }
+ break;
+
+ case Scope.CLASS_SCOPE :
+ SourceTypeBinding type = ((ClassScope)currentScope).referenceContext.binding;
+ ReferenceBinding[] memberTypes = type.memberTypes();
+ if (memberTypes != null) {
+ for (int j = 0; j < memberTypes.length; j++) {
+ if (memberTypes[j] == exceptionType) {
+ isQualified = false;
+ break done;
+ }
+ }
+ }
+
+
+ break;
+
+ case Scope.COMPILATION_UNIT_SCOPE :
+ SourceTypeBinding[] types = ((CompilationUnitScope)currentScope).topLevelTypes;
+ if (types != null) {
+ for (int j = 0; j < types.length; j++) {
+ if (types[j] == exceptionType) {
+ isQualified = false;
+ break done;
+ }
+ }
+ }
+ break done;
+ }
+ currentScope = currentScope.parent;
+ }
+
+ if (isQualified && mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, exceptionType.modifiers)) {
+ if (memberPackageName == null || memberPackageName.length == 0)
+ if (this.unitScope != null && this.unitScope.getDefaultPackage().compoundName != CharOperation.NO_CHAR_CHAR)
+ return; // ignore types from the default package from outside it
+ } else {
+ isQualified = false;
+ }
+
+ if (isQualified) {
+ completionName =
+ CharOperation.concat(
+ memberPackageName,
+ CharOperation.concat(
+ memberEnclosingTypeNames,
+ memberTypeName,
+ '.'),
+ '.');
+ }
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(typeName, exceptionType.sourceName);
+ relevance += computeRelevanceForExpectingType(exceptionType);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+ if(!insideQualifiedReference) {
+ relevance += computeRelevanceForQualification(isQualified);
+ }
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException();
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ createTypeProposal(exceptionType, exceptionType.qualifiedSourceName(), IAccessRule.K_ACCESSIBLE, completionName, relevance);
+ }
+ }
+
+ private void findExceptionFromTryStatement(
+ char[] typeName,
+ ReferenceBinding receiverType,
+ SourceTypeBinding invocationType,
+ BlockScope scope,
+ ObjectVector typesFound) {
+
+ for (int i = 0; i <= this.expectedTypesPtr; i++) {
+ ReferenceBinding exceptionType = (ReferenceBinding)this.expectedTypes[i];
+
+ findExceptionFromTryStatement(typeName, exceptionType, receiverType, invocationType, scope, typesFound, true);
+ }
+ }
+
+ private void findExplicitConstructors(
+ char[] name,
+ ReferenceBinding currentType,
+ MethodScope scope,
+ InvocationSite invocationSite) {
+
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)scope.referenceContext;
+ MethodBinding enclosingConstructor = constructorDeclaration.binding;
+
+ // No visibility checks can be performed without the scope & invocationSite
+ MethodBinding[] methods = currentType.availableMethods();
+ if(methods != null) {
+ next : for (int f = methods.length; --f >= 0;) {
+ MethodBinding constructor = methods[f];
+ if (constructor != enclosingConstructor && constructor.isConstructor()) {
+
+ if (this.options.checkDeprecation &&
+ constructor.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(constructor.declaringClass))
+ continue next;
+
+ if (this.options.checkVisibility
+ && !constructor.canBeSeenBy(invocationSite, scope)) continue next;
+
+ TypeBinding[] parameters = constructor.parameters;
+ int paramLength = parameters.length;
+
+ char[][] parameterPackageNames = new char[paramLength][];
+ char[][] parameterTypeNames = new char[paramLength][];
+ for (int i = 0; i < paramLength; i++) {
+ TypeBinding type = parameters[i];
+ parameterPackageNames[i] = type.qualifiedPackageName();
+ parameterTypeNames[i] = type.qualifiedSourceName();
+ }
+ char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
+
+ char[] completion = CharOperation.NO_CHAR;
+ if (this.source != null
+ && this.source.length > this.endPosition
+ && this.source[this.endPosition] == '(')
+ completion = name;
+ else
+ completion = CharOperation.concat(name, new char[] { '(', ')' });
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(this.completionToken, name);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(currentType));
+ proposal.setSignature(getSignature(constructor));
+ MethodBinding original = constructor.original();
+ if(original != constructor) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ //proposal.setPackageName(null);
+ //proposal.setTypeName(null);
+ proposal.setName(name);
+ proposal.setIsContructor(true);
+ proposal.setCompletion(completion);
+ proposal.setFlags(constructor.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private void findConstructors(
+ ReferenceBinding currentType,
+ TypeBinding[] argTypes,
+ Scope scope,
+ InvocationSite invocationSite,
+ boolean forAnonymousType) {
+
+ // No visibility checks can be performed without the scope & invocationSite
+ MethodBinding[] methods = currentType.availableMethods();
+ if(methods != null) {
+ int minArgLength = argTypes == null ? 0 : argTypes.length;
+ next : for (int f = methods.length; --f >= 0;) {
+ MethodBinding constructor = methods[f];
+ if (constructor.isConstructor()) {
+
+ if (this.options.checkDeprecation &&
+ constructor.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(constructor.declaringClass))
+ continue next;
+
+ if (this.options.checkVisibility
+ && !constructor.canBeSeenBy(invocationSite, scope)) {
+ if(!forAnonymousType || !constructor.isProtected())
+ continue next;
+ }
+
+ TypeBinding[] parameters = constructor.parameters;
+ int paramLength = parameters.length;
+ if (minArgLength > paramLength)
+ continue next;
+ for (int a = minArgLength; --a >= 0;)
+ if (argTypes[a] != null) { // can be null if it could not be resolved properly
+ if (!argTypes[a].isCompatibleWith(constructor.parameters[a]))
+ continue next;
+ }
+
+ char[][] parameterPackageNames = new char[paramLength][];
+ char[][] parameterTypeNames = new char[paramLength][];
+ for (int i = 0; i < paramLength; i++) {
+ TypeBinding type = parameters[i];
+ parameterPackageNames[i] = type.qualifiedPackageName();
+ parameterTypeNames[i] = type.qualifiedSourceName();
+ }
+ char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
+
+ char[] bindingName = constructor.selector;
+ char[] completion = bindingName;
+ if (this.source != null
+ && this.source.length > this.endPosition
+ && this.source[this.endPosition] == '(') {
+ completion = bindingName;
+ } else {
+ completion = CharOperation.concat(bindingName, new char[] { '(', ')' });
+ }
+
+ if(forAnonymousType){
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(currentType));
+ proposal.setDeclarationKey(currentType.computeUniqueKey());
+ proposal.setSignature(getSignature(constructor));
+ MethodBinding original = constructor.original();
+ if(original != constructor) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setKey(constructor.computeUniqueKey());
+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ //proposal.setPackageName(null);
+ //proposal.setTypeName(null);
+ proposal.setCompletion(completion);
+ proposal.setFlags(constructor.modifiers);
+ proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ } else {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ // Special case for completion in javadoc
+ if (this.assistNodeInJavadoc > 0) {
+ Expression receiver = null;
+ char[] selector = null;
+ if (invocationSite instanceof CompletionOnJavadocAllocationExpression) {
+ CompletionOnJavadocAllocationExpression alloc = (CompletionOnJavadocAllocationExpression) invocationSite;
+ receiver = alloc.type;
+ } else if (invocationSite instanceof CompletionOnJavadocFieldReference) {
+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite;
+ receiver = fieldRef.receiver;
+ }
+ if (receiver != null) {
+ StringBuffer javadocCompletion = new StringBuffer();
+ if (receiver.isThis()) {
+ selector = (((JavadocImplicitTypeReference)receiver).token);
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
+ javadocCompletion.append('#');
+ }
+ } else if (receiver instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver;
+ selector = typeRef.token;
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
+ javadocCompletion.append(typeRef.token);
+ javadocCompletion.append('#');
+ }
+ } else if (receiver instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver;
+ selector = typeRef.tokens[typeRef.tokens.length-1];
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
+ javadocCompletion.append(CharOperation.concatWith(typeRef.tokens, '.'));
+ javadocCompletion.append('#');
+ }
+ }
+ // Append parameters types
+ javadocCompletion.append(selector);
+ javadocCompletion.append('(');
+ if (constructor.parameters != null) {
+ boolean isVarargs = constructor.isVarargs();
+ for (int p=0, ln=constructor.parameters.length; p0) javadocCompletion.append(", "); //$NON-NLS-1$
+ TypeBinding argTypeBinding = constructor.parameters[p];
+ if (isVarargs && p == ln - 1) {
+ createVargsType(argTypeBinding, javadocCompletion);
+ } else {
+ createType(argTypeBinding, javadocCompletion);
+ }
+ }
+ }
+ javadocCompletion.append(')');
+ completion = javadocCompletion.toString().toCharArray();
+ }
+ }
+
+ // Create standard proposal
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(currentType));
+ proposal.setSignature(getSignature(constructor));
+ MethodBinding original = constructor.original();
+ if(original != constructor) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ proposal.setName(currentType.sourceName());
+ proposal.setIsContructor(true);
+ proposal.setCompletion(completion);
+ proposal.setFlags(constructor.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_METHOD_REF)) {
+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(currentType));
+ proposal.setSignature(getSignature(constructor));
+ MethodBinding original = constructor.original();
+ if(original != constructor) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName());
+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ //proposal.setPackageName(null);
+ //proposal.setTypeName(null);
+ proposal.setName(currentType.sourceName());
+ proposal.setIsContructor(true);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags(constructor.modifiers);
+ int start = (this.assistNodeInJavadoc > 0) ? this.startPosition : this.endPosition;
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0) start = this.javadocTagPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
+ private void findFields(
+ char[] fieldName,
+ FieldBinding[] fields,
+ Scope scope,
+ ObjectVector fieldsFound,
+ ObjectVector localsFound,
+ boolean onlyStaticFields,
+ ReferenceBinding receiverType,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ boolean implicitCall,
+ boolean canBePrefixed,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean missingElementsHaveProblems) {
+
+ ObjectVector newFieldsFound = new ObjectVector();
+ // Inherited fields which are hidden by subclasses are filtered out
+ // No visibility checks can be performed without the scope & invocationSite
+
+ int fieldLength = fieldName.length;
+ next : for (int f = fields.length; --f >= 0;) {
+ FieldBinding field = fields[f];
+
+ if (onlyStaticFields && !field.isStatic()) continue next;
+
+ if (fieldLength > field.name.length) continue next;
+
+ if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) continue next;
+
+ if (this.options.checkDeprecation &&
+ field.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(field.declaringClass))
+ continue next;
+
+ if (this.options.checkVisibility
+ && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+
+ boolean prefixRequired = false;
+
+ for (int i = fieldsFound.size; --i >= 0;) {
+ Object[] other = (Object[])fieldsFound.elementAt(i);
+ FieldBinding otherField = (FieldBinding) other[0];
+ ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
+ if (field == otherField && receiverType == otherReceiverType)
+ continue next;
+ if (CharOperation.equals(field.name, otherField.name, true)) {
+ if (field.declaringClass.isSuperclassOf(otherField.declaringClass))
+ continue next;
+ if(canBePrefixed) {
+ prefixRequired = true;
+ } else {
+ continue next;
+ }
+ }
+ }
+
+ for (int l = localsFound.size; --l >= 0;) {
+ LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l);
+
+ if (CharOperation.equals(field.name, local.name, true)) {
+ SourceTypeBinding declarationType = scope.enclosingSourceType();
+ if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) {
+ continue next;
+ }
+ if(canBePrefixed) {
+ prefixRequired = true;
+ } else {
+ continue next;
+ }
+ break;
+ }
+ }
+
+ newFieldsFound.add(new Object[]{field, receiverType});
+
+ char[] completion = field.name;
+
+ if(prefixRequired || this.options.forceImplicitQualification){
+ char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
+ completion = CharOperation.concat(prefix,completion,'.');
+ }
+
+ // Special case for javadoc completion
+ if (this.assistNodeInJavadoc > 0) {
+ if (invocationSite instanceof CompletionOnJavadocFieldReference) {
+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite;
+ if (fieldRef.receiver.isThis()) {
+ if (fieldRef.completeInText()) {
+ completion = CharOperation.concat(new char[] { '#' }, field.name);
+ }
+ } else if (fieldRef.completeInText()) {
+ if (fieldRef.receiver instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) fieldRef.receiver;
+ completion = CharOperation.concat(typeRef.token, field.name, '#');
+ } else if (fieldRef.receiver instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) fieldRef.receiver;
+ completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), field.name, '#');
+ }
+ }
+ }
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal(field);
+ if (fieldName != null) relevance += computeRelevanceForCaseMatching(fieldName, field.name);
+ relevance += computeRelevanceForExpectingType(field.type);
+ relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic());
+ relevance += computeRelevanceForQualification(prefixRequired);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+ if (onlyStaticFields && this.insideQualifiedReference) {
+ relevance += computeRelevanceForInheritance(receiverType, field.declaringClass);
+ }
+ if (missingElements != null) {
+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
+ }
+
+ this.noProposal = false;
+ // Standard proposal
+ if (!this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(field.declaringClass));
+ proposal.setSignature(getSignature(field.type));
+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+ proposal.setPackageName(field.type.qualifiedPackageName());
+ proposal.setTypeName(field.type.qualifiedSourceName());
+ proposal.setName(field.name);
+ if (missingElements != null) {
+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
+ for (int i = 0; i < missingElements.length; i++) {
+ subProposals[i] =
+ createRequiredTypeProposal(
+ missingElements[i],
+ missingElementsStarts[i],
+ missingElementsEnds[i],
+ relevance);
+ }
+ proposal.setRequiredProposals(subProposals);
+ }
+ proposal.setCompletion(completion);
+ proposal.setFlags(field.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Javadoc completions
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_FIELD_REF)) {
+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_FIELD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(field.declaringClass));
+ proposal.setSignature(getSignature(field.type));
+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+ proposal.setPackageName(field.type.qualifiedPackageName());
+ proposal.setTypeName(field.type.qualifiedSourceName());
+ proposal.setName(field.name);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags(field.modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+
+ fieldsFound.addAll(newFieldsFound);
+ }
+
+ private void findFields(
+ char[] fieldName,
+ ReferenceBinding receiverType,
+ Scope scope,
+ ObjectVector fieldsFound,
+ ObjectVector localsFound,
+ boolean onlyStaticFields,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ boolean implicitCall,
+ boolean canBePrefixed,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean missingElementsHaveProblems) {
+
+ boolean notInJavadoc = this.assistNodeInJavadoc == 0;
+ if (fieldName == null && notInJavadoc)
+ return;
+
+ ReferenceBinding currentType = receiverType;
+ do {
+
+ FieldBinding[] fields = currentType.availableFields();
+ if(fields != null && fields.length > 0) {
+ findFields(
+ fieldName,
+ fields,
+ scope,
+ fieldsFound,
+ localsFound,
+ onlyStaticFields,
+ receiverType,
+ invocationSite,
+ invocationScope,
+ implicitCall,
+ canBePrefixed,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds,
+ missingElementsHaveProblems);
+ }
+
+ currentType = currentType.superclass();
+ } while (notInJavadoc && currentType != null);
+ }
+
+ protected void findFieldsAndMethods(
+ char[] token,
+ TypeBinding receiverType,
+ Scope scope,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ boolean staticsOnly,
+ boolean implicitCall,
+ boolean superCall,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean missingElementsHaveProblems) {
+
+ if (token == null)
+ return;
+
+ if (receiverType.isBaseType())
+ return; // nothing else is possible with base types
+
+ boolean proposeField = !this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null);
+ boolean proposeMethod = !this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null);
+
+ ObjectVector methodsFound = new ObjectVector();
+ ObjectVector fieldsFound = new ObjectVector();
+
+ if(proposeField) {
+ findFields(
+ token,
+ (ReferenceBinding) receiverType,
+ scope,
+ fieldsFound,
+ new ObjectVector(),
+ staticsOnly,
+ invocationSite,
+ invocationScope,
+ implicitCall,
+ false,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds,
+ missingElementsHaveProblems);
+ }
+
+ if(proposeMethod) {
+ findMethods(
+ token,
+ null,
+ null,
+ (ReferenceBinding) receiverType,
+ scope,
+ methodsFound,
+ staticsOnly,
+ false,
+ false,
+ invocationSite,
+ invocationScope,
+ implicitCall,
+ superCall,
+ false,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds,
+ missingElementsHaveProblems);
+ }
+ }
+
+ private void findFieldsAndMethodsFromFavorites(
+ char[] token,
+ Scope scope,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ ObjectVector localsFound,
+ ObjectVector fieldsFound,
+ ObjectVector methodsFound) {
+
+ ImportBinding[] favoriteBindings = getFavoriteReferenceBindings(invocationScope);
+
+ if (favoriteBindings != null && favoriteBindings.length > 0) {
+ for (int i = 0; i < favoriteBindings.length; i++) {
+ ImportBinding favoriteBinding = favoriteBindings[i];
+ switch (favoriteBinding.resolvedImport.kind()) {
+ case Binding.FIELD:
+ FieldBinding fieldBinding = (FieldBinding) favoriteBinding.resolvedImport;
+ findFieldsFromFavorites(
+ token,
+ new FieldBinding[]{fieldBinding},
+ scope,
+ fieldsFound,
+ localsFound,
+ fieldBinding.declaringClass,
+ invocationSite,
+ invocationScope);
+ break;
+ case Binding.METHOD:
+ MethodBinding methodBinding = (MethodBinding) favoriteBinding.resolvedImport;
+ MethodBinding[] methods = methodBinding.declaringClass.availableMethods();
+ long range;
+ if ((range = ReferenceBinding.binarySearch(methodBinding.selector, methods)) >= 0) {
+ int start = (int) range, end = (int) (range >> 32);
+ int length = end - start + 1;
+ System.arraycopy(methods, start, methods = new MethodBinding[length], 0, length);
+ } else {
+ methods = Binding.NO_METHODS;
+ }
+ findLocalMethodsFromFavorites(
+ token,
+ methods,
+ scope,
+ methodsFound,
+ methodBinding.declaringClass,
+ invocationSite,
+ invocationScope);
+ break;
+ case Binding.TYPE:
+ ReferenceBinding referenceBinding = (ReferenceBinding) favoriteBinding.resolvedImport;
+ if(favoriteBinding.onDemand) {
+ findFieldsFromFavorites(
+ token,
+ referenceBinding.availableFields(),
+ scope,
+ fieldsFound,
+ localsFound,
+ referenceBinding,
+ invocationSite,
+ invocationScope);
+
+ findLocalMethodsFromFavorites(
+ token,
+ referenceBinding.availableMethods(),
+ scope,
+ methodsFound,
+ referenceBinding,
+ invocationSite,
+ invocationScope);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void findFieldsAndMethodsFromMissingFieldType(
+ char[] token,
+ Scope scope,
+ InvocationSite invocationSite,
+ boolean insideTypeAnnotation) {
+
+ boolean staticsOnly = false;
+ Scope currentScope = scope;
+
+ done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (currentScope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+ MethodScope methodScope = (MethodScope) currentScope;
+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+
+ case Scope.BLOCK_SCOPE :
+ break;
+
+ case Scope.CLASS_SCOPE :
+ ClassScope classScope = (ClassScope) currentScope;
+ SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+ if(!insideTypeAnnotation) {
+
+ FieldDeclaration[] fields = classScope.referenceContext.fields;
+
+ int fieldsCount = fields == null ? 0 : fields.length;
+ for (int i = 0; i < fieldsCount; i++) {
+ FieldDeclaration fieldDeclaration = fields[i];
+ if (CharOperation.equals(fieldDeclaration.name, token)) {
+ if (fieldDeclaration.binding == null) {
+ findFieldsAndMethodsFromMissingType(
+ this.completionToken,
+ fieldDeclaration.type,
+ currentScope,
+ invocationSite,
+ scope);
+ }
+ break done;
+ }
+ }
+ }
+ staticsOnly |= enclosingType.isStatic();
+ insideTypeAnnotation = false;
+ break;
+ case Scope.COMPILATION_UNIT_SCOPE :
+ break done;
+ }
+ currentScope = currentScope.parent;
+ }
+ }
+
+ private void findFieldsAndMethodsFromMissingReturnType(
+ char[] token,
+ TypeBinding[] arguments,
+ Scope scope,
+ InvocationSite invocationSite,
+ boolean insideTypeAnnotation) {
+
+ boolean staticsOnly = false;
+ Scope currentScope = scope;
+
+ done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (currentScope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+ MethodScope methodScope = (MethodScope) currentScope;
+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+
+ case Scope.BLOCK_SCOPE :
+ break;
+
+ case Scope.CLASS_SCOPE :
+ ClassScope classScope = (ClassScope) currentScope;
+ SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+ if(!insideTypeAnnotation) {
+
+ AbstractMethodDeclaration[] methods = classScope.referenceContext.methods;
+
+ int methodsCount = methods == null ? 0 : methods.length;
+ for (int i = 0; i < methodsCount; i++) {
+ AbstractMethodDeclaration methodDeclaration = methods[i];
+ if (methodDeclaration instanceof MethodDeclaration &&
+ CharOperation.equals(methodDeclaration.selector, token)) {
+ MethodDeclaration method = (MethodDeclaration) methodDeclaration;
+ if (methodDeclaration.binding == null) {
+ Argument[] parameters = method.arguments;
+ int parametersLength = parameters == null ? 0 : parameters.length;
+ int argumentsLength = arguments == null ? 0 : arguments.length;
+
+ if (parametersLength == 0) {
+ if (argumentsLength == 0) {
+ findFieldsAndMethodsFromMissingType(
+ this.completionToken,
+ method.returnType,
+ currentScope,
+ invocationSite,
+ scope);
+ break done;
+ }
+ } else {
+ TypeBinding[] parametersBindings = new TypeBinding[parametersLength];
+ for (int j = 0; j < parametersLength; j++) {
+ parametersBindings[j] = parameters[j].type.resolvedType;
+ }
+ if(areParametersCompatibleWith(parametersBindings, arguments, parameters[parametersLength - 1].isVarArgs())) {
+ findFieldsAndMethodsFromMissingType(
+ this.completionToken,
+ method.returnType,
+ currentScope,
+ invocationSite,
+ scope);
+ break done;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ staticsOnly |= enclosingType.isStatic();
+ insideTypeAnnotation = false;
+ break;
+ case Scope.COMPILATION_UNIT_SCOPE :
+ break done;
+ }
+ currentScope = currentScope.parent;
+ }
+ }
+
+ private void findFieldsAndMethodsFromMissingType(
+ final char[] token,
+ TypeReference typeRef,
+ final Scope scope,
+ final InvocationSite invocationSite,
+ final Scope invocationScope) {
+ MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this);
+ MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor =
+ new MissingTypesGuesser.GuessedTypeRequestor() {
+ public void accept(
+ TypeBinding guessedType,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean hasProblems) {
+ findFieldsAndMethods(
+ CompletionEngine.this.completionToken,
+ guessedType,
+ scope,
+ invocationSite,
+ invocationScope,
+ false,
+ false,
+ false,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds,
+ hasProblems);
+
+ }
+ };
+ missingTypesConverter.guess(typeRef, scope, substitutionRequestor);
+ }
+
+ private void findFieldsFromFavorites(
+ char[] fieldName,
+ FieldBinding[] fields,
+ Scope scope,
+ ObjectVector fieldsFound,
+ ObjectVector localsFound,
+ ReferenceBinding receiverType,
+ InvocationSite invocationSite,
+ Scope invocationScope) {
+
+ char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.');
+
+ int fieldLength = fieldName.length;
+ next : for (int f = fields.length; --f >= 0;) {
+ FieldBinding field = fields[f];
+
+ // only static fields must be proposed
+ if (!field.isStatic()) continue next;
+
+ if (fieldLength > field.name.length) continue next;
+
+ if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) continue next;
+
+ if (this.options.checkDeprecation &&
+ field.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(field.declaringClass))
+ continue next;
+
+ if (this.options.checkVisibility
+ && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+
+ for (int i = fieldsFound.size; --i >= 0;) {
+ Object[] other = (Object[])fieldsFound.elementAt(i);
+ FieldBinding otherField = (FieldBinding) other[0];
+
+ if (field == otherField) continue next;
+ }
+
+ fieldsFound.add(new Object[]{field, receiverType});
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal(field);
+ if (fieldName != null) relevance += computeRelevanceForCaseMatching(fieldName, field.name);
+ relevance += computeRelevanceForExpectingType(field.type);
+ relevance += computeRelevanceForStatic(true, true);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ CompilationUnitDeclaration cu = this.unitScope.referenceContext;
+ int importStart = cu.types[0].declarationSourceStart;
+ int importEnd = importStart;
+
+ this.noProposal = false;
+
+ if (this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5 ||
+ !this.options.suggestStaticImport) {
+ if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) {
+ char[] completion = CharOperation.concat(receiverType.sourceName, field.name, '.');
+
+ CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(field.declaringClass));
+ proposal.setSignature(getSignature(field.type));
+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+ proposal.setPackageName(field.type.qualifiedPackageName());
+ proposal.setTypeName(field.type.qualifiedSourceName());
+ proposal.setName(field.name);
+ proposal.setCompletion(completion);
+ proposal.setFlags(field.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+
+ char[] typeImportCompletion = createImportCharArray(typeName, false, false);
+
+ CompletionProposal typeImportProposal = this.createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition);
+ typeImportProposal.nameLookup = this.nameEnvironment.nameLookup;
+ typeImportProposal.completionEngine = this;
+ char[] packageName = receiverType.qualifiedPackageName();
+ typeImportProposal.setDeclarationSignature(packageName);
+ typeImportProposal.setSignature(getSignature(receiverType));
+ typeImportProposal.setPackageName(packageName);
+ typeImportProposal.setTypeName(receiverType.qualifiedSourceName());
+ typeImportProposal.setCompletion(typeImportCompletion);
+ typeImportProposal.setFlags(receiverType.modifiers);
+ typeImportProposal.setAdditionalFlags(CompletionFlags.Default);
+ typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
+ typeImportProposal.setRelevance(relevance);
+
+ proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal});
+
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ } else {
+ if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.FIELD_IMPORT)) {
+ char[] completion = field.name;
+
+ CompletionProposal proposal = this.createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(field.declaringClass));
+ proposal.setSignature(getSignature(field.type));
+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+ proposal.setPackageName(field.type.qualifiedPackageName());
+ proposal.setTypeName(field.type.qualifiedSourceName());
+ proposal.setName(field.name);
+ proposal.setCompletion(completion);
+ proposal.setFlags(field.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+
+ char[] fieldImportCompletion = createImportCharArray(CharOperation.concat(typeName, field.name, '.'), true, false);
+
+ CompletionProposal fieldImportProposal = this.createProposal(CompletionProposal.FIELD_IMPORT, this.actualCompletionPosition);
+ fieldImportProposal.setDeclarationSignature(getSignature(field.declaringClass));
+ fieldImportProposal.setSignature(getSignature(field.type));
+ fieldImportProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName());
+ fieldImportProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName());
+ fieldImportProposal.setPackageName(field.type.qualifiedPackageName());
+ fieldImportProposal.setTypeName(field.type.qualifiedSourceName());
+ fieldImportProposal.setName(field.name);
+ fieldImportProposal.setCompletion(fieldImportCompletion);
+ fieldImportProposal.setFlags(field.modifiers);
+ fieldImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
+ fieldImportProposal.setRelevance(relevance);
+
+ proposal.setRequiredProposals(new CompletionProposal[]{fieldImportProposal});
+
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ }
+
+ private void findImports(CompletionOnImportReference importReference, boolean findMembers) {
+ char[][] tokens = importReference.tokens;
+
+ char[] importName = CharOperation.concatWith(tokens, '.');
+
+ if (importName.length == 0)
+ return;
+
+ char[] lastToken = tokens[tokens.length - 1];
+ if(lastToken != null && lastToken.length == 0)
+ importName = CharOperation.concat(importName, new char[]{'.'});
+
+ this.resolvingImports = true;
+
+ this.completionToken = importName;
+ // want to replace the existing .*;
+// if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+// this.nameEnvironment.findPackages(importName, this);
+// }
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ this.nameEnvironment.findTypes(
+ importName,
+ findMembers,
+ this.options.camelCaseMatch,
+ IJavaScriptSearchConstants.TYPE,
+ this);
+ acceptTypes(null);
+ }
+ }
+
+ private void findImportsOfMemberTypes(char[] typeName, ReferenceBinding ref) {
+ ReferenceBinding[] memberTypes = ref.memberTypes();
+
+ int typeLength = typeName.length;
+ next : for (int m = memberTypes.length; --m >= 0;) {
+ ReferenceBinding memberType = memberTypes[m];
+ // if (!wantClasses && memberType.isClass()) continue next;
+ // if (!wantInterfaces && memberType.isInterface()) continue next;
+
+ if (typeLength > memberType.sourceName.length)
+ continue next;
+
+ if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false/* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, memberType.sourceName)))
+ continue next;
+
+ if (this.options.checkDeprecation && memberType.isViewedAsDeprecated()) continue next;
+
+ if (this.options.checkVisibility
+ && !memberType.canBeSeenBy(this.unitScope.getDefaultPackage()))
+ continue next;
+
+ char[] completionName = CharOperation.concat(
+ memberType.qualifiedPackageName(),
+ memberType.qualifiedSourceName(),
+ '.');
+
+ completionName = CharOperation.concat(completionName, SEMICOLON);
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ if (memberType.isClass()) {
+ relevance += computeRelevanceForClass();
+ }
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ createTypeProposal(memberType, memberType.qualifiedSourceName(), IAccessRule.K_ACCESSIBLE, completionName, relevance);
+ }
+ }
+ }
+
+ /*
+ * Find javadoc block tags for a given completion javadoc tag node
+ */
+ private void findJavadocBlockTags(CompletionOnJavadocTag javadocTag) {
+ char[][] possibleTags = javadocTag.getPossibleBlockTags();
+ if (possibleTags == null) return;
+ int length = possibleTags.length;
+ for (int i=0; i 0)
+ for (int i = 0; i < choices.length; i++)
+ if (length <= choices[i].length
+ && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */
+ )){
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
+ if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED;
+
+ if(CharOperation.equals(choices[i], Keywords.TRUE) || CharOperation.equals(choices[i], Keywords.FALSE)) {
+ relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN);
+ relevance += computeRelevanceForQualification(false);
+ }
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
+ proposal.setName(choices[i]);
+ proposal.setCompletion(choices[i]);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ private void findTrueOrFalseKeywords(char[][] choices) {
+ if(choices == null || choices.length == 0) return;
+
+ if(this.expectedTypesPtr != 0 || this.expectedTypes[0] != TypeBinding.BOOLEAN) return;
+
+ for (int i = 0; i < choices.length; i++) {
+ if (CharOperation.equals(choices[i], Keywords.TRUE) ||
+ CharOperation.equals(choices[i], Keywords.FALSE)
+ ){
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(CharOperation.NO_CHAR, choices[i]);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
+ relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN);
+ relevance += computeRelevanceForQualification(false);
+ relevance += R_TRUE_OR_FALSE;
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition);
+ proposal.setName(choices[i]);
+ proposal.setCompletion(choices[i]);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ }
+
+ private void findKeywordsForMember(char[] token, int modifiers) {
+ char[][] keywords = new char[Keywords.COUNT][];
+ int count = 0;
+
+ // visibility
+ if((modifiers & ClassFileConstants.AccPrivate) == 0
+ && (modifiers & ClassFileConstants.AccProtected) == 0
+ && (modifiers & ClassFileConstants.AccPublic) == 0) {
+ keywords[count++] = Keywords.PROTECTED;
+ keywords[count++] = Keywords.PUBLIC;
+ if((modifiers & ClassFileConstants.AccAbstract) == 0) {
+ keywords[count++] = Keywords.PRIVATE;
+ }
+ }
+
+ if((modifiers & ClassFileConstants.AccAbstract) == 0) {
+ // abtract
+ if((modifiers & ~(ExtraCompilerModifiers.AccVisibilityMASK | ClassFileConstants.AccStatic)) == 0) {
+ keywords[count++] = Keywords.ABSTRACT;
+ }
+
+ // final
+ if((modifiers & ClassFileConstants.AccFinal) == 0) {
+ keywords[count++] = Keywords.FINAL;
+ }
+
+ // static
+ if((modifiers & ClassFileConstants.AccStatic) == 0) {
+ keywords[count++] = Keywords.STATIC;
+ }
+
+ boolean canBeField = true;
+ boolean canBeMethod = true;
+ boolean canBeType = true;
+ if((modifiers & ClassFileConstants.AccNative) != 0
+ || (modifiers & ClassFileConstants.AccStrictfp) != 0) {
+ canBeField = false;
+ canBeType = false;
+ }
+
+
+ if(canBeField) {
+ // transient
+ keywords[count++] = Keywords.TRANSIENT;
+
+
+ // volatile
+ keywords[count++] = Keywords.VOLATILE;
+ }
+
+ if(canBeMethod) {
+ // native
+ if((modifiers & ClassFileConstants.AccNative) == 0) {
+ keywords[count++] = Keywords.NATIVE;
+ }
+
+ // strictfp
+ if((modifiers & ClassFileConstants.AccStrictfp) == 0) {
+ keywords[count++] = Keywords.STRICTFP;
+ }
+
+ // synchronized
+ keywords[count++] = Keywords.SYNCHRONIZED;
+
+ }
+
+ if(canBeType) {
+ keywords[count++] = Keywords.CLASS;
+ keywords[count++] = Keywords.INTERFACE;
+ }
+ } else {
+ // class
+ keywords[count++] = Keywords.CLASS;
+ keywords[count++] = Keywords.INTERFACE;
+ }
+ System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
+
+ findKeywords(token, keywords, false, false);
+ }
+
+ private void findMemberTypes(
+ char[] typeName,
+ ReferenceBinding receiverType,
+ Scope scope,
+ SourceTypeBinding typeInvocation,
+ boolean staticOnly,
+ boolean staticFieldsAndMethodOnly,
+ ObjectVector typesFound) {
+ findMemberTypes(
+ typeName,
+ receiverType,
+ scope,
+ typeInvocation,
+ staticOnly,
+ staticFieldsAndMethodOnly,
+ false,
+ false,
+ false,
+ null,
+ typesFound);
+ }
+ private void findMemberTypes(
+ char[] typeName,
+ ReferenceBinding receiverType,
+ Scope scope,
+ SourceTypeBinding typeInvocation,
+ boolean staticOnly,
+ boolean staticFieldsAndMethodOnly,
+ boolean fromStaticImport,
+ boolean checkQualification,
+ boolean proposeAllMemberTypes,
+ SourceTypeBinding typeToIgnore,
+ ObjectVector typesFound) {
+
+ ReferenceBinding currentType = receiverType;
+ if (typeName == null)
+ return;
+
+ if (this.assistNodeIsSuperType && !this.insideQualifiedReference) return; // we're trying to find a supertype
+
+ return; // we're trying to find a supertype
+ }
+
+ /*
+ * Find javadoc parameter names.
+ */
+ private void findJavadocParamNames(char[] token, char[][] missingParams, boolean isTypeParam) {
+
+ if (missingParams == null) return;
+
+ // Get relevance
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for param name
+ if (!isTypeParam) relevance += R_INTERESTING;
+
+ // Propose missing param
+ int length = missingParams.length;
+ relevance += length;
+ for (int i=0; i') : argName;
+ proposal.setCompletion(completion);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(--relevance);
+ this.requestor.accept(proposal);
+ if (DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ }
+
+ private void findSubMemberTypes(
+ char[] typeName,
+ ReferenceBinding receiverType,
+ Scope scope,
+ SourceTypeBinding typeInvocation,
+ boolean staticOnly,
+ boolean staticFieldsAndMethodOnly,
+ boolean fromStaticImport,
+ ObjectVector typesFound) {
+
+ ReferenceBinding currentType = receiverType;
+ if (typeName == null || typeName.length == 0)
+ return;
+
+ return; // we're trying to find a supertype
+ }
+
+ private void findImplicitMessageSends(
+ char[] token,
+ TypeBinding[] argTypes,
+ Scope scope,
+ InvocationSite invocationSite,
+ Scope invocationScope) {
+
+ if (token == null)
+ return;
+
+ boolean staticsOnly = false;
+ // need to know if we're in a static context (or inside a constructor)
+ ObjectVector methodsFound = new ObjectVector();
+
+ done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (scope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+ MethodScope methodScope = (MethodScope) scope;
+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+ break;
+
+ case Scope.CLASS_SCOPE :
+ ClassScope classScope = (ClassScope) scope;
+ SourceTypeBinding enclosingType = classScope.getReferenceBinding();
+ findMethods(
+ token,
+ null,
+ argTypes,
+ enclosingType,
+ classScope,
+ methodsFound,
+ staticsOnly,
+ true,
+ false,
+ invocationSite,
+ invocationScope,
+ true,
+ false,
+ true,
+ null,
+ null,
+ null,
+ false);
+ staticsOnly |= enclosingType.isStatic();
+ break;
+
+ case Scope.COMPILATION_UNIT_SCOPE :
+ CompilationUnitScope compScope = (CompilationUnitScope) scope;
+ CompilationUnitBinding compBinding = compScope.enclosingCompilationUnit();
+ findMethods(
+ token,
+ null,
+ argTypes,
+ compBinding,
+ compScope,
+ methodsFound,
+ staticsOnly,
+ false,
+ false,
+ invocationSite,
+ invocationScope,
+ true,
+ false,
+ true,
+ null,
+ null,
+ null,
+ false);
+ break done;
+ }
+ scope = scope.parent;
+ }
+ }
+
+ // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
+ private void findLocalMethods(
+ char[] methodName,
+ TypeBinding[] typeArgTypes,
+ TypeBinding[] argTypes,
+ MethodBinding[] methods,
+ int numberMethods,
+ Scope scope,
+ ObjectVector methodsFound,
+ boolean onlyStaticMethods,
+ boolean exactMatch,
+ ReferenceBinding receiverType,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ boolean implicitCall,
+ boolean superCall,
+ boolean canBePrefixed,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean missingElementsHaveProblems) {
+
+ ObjectVector newMethodsFound = new ObjectVector();
+ // Inherited methods which are hidden by subclasses are filtered out
+ // No visibility checks can be performed without the scope & invocationSite
+
+ int methodLength = methodName.length;
+ int minTypeArgLength = typeArgTypes == null ? 0 : typeArgTypes.length;
+ int minArgLength = argTypes == null ? 0 : argTypes.length;
+
+ next : for (int f = numberMethods; --f >= 0;) {
+ MethodBinding method = methods[f];
+
+ if (method.isDefaultAbstract()) continue next;
+
+ if (method.isConstructor()) continue next;
+
+ if (this.options.checkDeprecation &&
+ method.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(method.declaringClass))
+ continue next;
+
+ //TODO (david) perhaps the relevance of a void method must be lesser than other methods
+ //if (expectedTypesPtr > -1 && method.returnType == BaseTypes.VoidBinding) continue next;
+
+ if (onlyStaticMethods && !method.isStatic()) continue next;
+
+ if (this.options.checkVisibility) {
+ if(method instanceof ProblemMethodBinding && method.declaringClass == null) continue next;
+ if(!method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+ }
+
+ if(superCall && method.isAbstract()) {
+ methodsFound.add(new Object[]{method, receiverType});
+ continue next;
+ }
+
+ if (exactMatch) {
+ if (!CharOperation.equals(methodName, method.selector, false /* ignore case */)) {
+ continue next;
+ }
+ } else {
+ if (methodLength > method.selector.length) continue next;
+ if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) {
+ continue next;
+ }
+ }
+
+ if (minTypeArgLength != 0 && minTypeArgLength != 0)
+ continue next;
+
+ if (minArgLength > method.parameters.length)
+ continue next;
+
+ for (int a = minArgLength; --a >= 0;){
+ if (argTypes[a] != null) { // can be null if it could not be resolved properly
+ if (!argTypes[a].isCompatibleWith(method.parameters[a])) {
+ continue next;
+ }
+ }
+ }
+
+ boolean prefixRequired = false;
+
+ for (int i = methodsFound.size; --i >= 0;) {
+ Object[] other = (Object[]) methodsFound.elementAt(i);
+ MethodBinding otherMethod = (MethodBinding) other[0];
+ ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
+ if (method == otherMethod && receiverType == otherReceiverType)
+ continue next;
+
+ if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
+ if (receiverType == otherReceiverType) {
+ if (lookupEnvironment.methodVerifier().doesMethodOverride(otherMethod, method)) {
+ continue next;
+ }
+ } else {
+ if (lookupEnvironment.methodVerifier().doesMethodOverride(otherMethod, method)) {
+ if(receiverType.isAnonymousType()) continue next;
+
+ if(!superCall) {
+ if(!canBePrefixed) continue next;
+
+ prefixRequired = true;
+ }
+ }
+ }
+ }
+ }
+
+ newMethodsFound.add(new Object[]{method, receiverType});
+
+// ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeWithSameErasure(method.declaringClass);
+// if (method.declaringClass != superTypeWithSameErasure) {
+// FunctionBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector);
+// for (int i = 0; i < otherMethods.length; i++) {
+// if(otherMethods[i].original() == method.original()) {
+// method = otherMethods[i];
+// }
+// }
+// }
+
+ int length = method.parameters.length;
+ char[][] parameterPackageNames = new char[length][];
+ char[][] parameterTypeNames = new char[length][];
+
+ for (int i = 0; i < length; i++) {
+ TypeBinding type = method.original().parameters[i];
+ parameterPackageNames[i] = type.qualifiedPackageName();
+ parameterTypeNames[i] = type.qualifiedSourceName();
+ }
+ char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
+
+ char[] completion = CharOperation.NO_CHAR;
+
+ int previousStartPosition = this.startPosition;
+
+ // Special case for completion in javadoc
+ if (this.assistNodeInJavadoc > 0) {
+ Expression receiver = null;
+ if (invocationSite instanceof CompletionOnJavadocMessageSend) {
+ CompletionOnJavadocMessageSend msg = (CompletionOnJavadocMessageSend) invocationSite;
+ receiver = msg.receiver;
+ } else if (invocationSite instanceof CompletionOnJavadocFieldReference) {
+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite;
+ receiver = fieldRef.receiver;
+ }
+ if (receiver != null) {
+ StringBuffer javadocCompletion = new StringBuffer();
+ if (receiver.isThis()) {
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
+ javadocCompletion.append('#');
+ }
+ } else if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) {
+ if (receiver instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver;
+ javadocCompletion.append(typeRef.token);
+ javadocCompletion.append('#');
+ } else if (receiver instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver;
+ completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), method.selector, '#');
+ for (int t=0,nt =typeRef.tokens.length; t0) javadocCompletion.append('.');
+ javadocCompletion.append(typeRef.tokens[t]);
+ }
+ javadocCompletion.append('#');
+ }
+ }
+ javadocCompletion.append(method.selector);
+ // Append parameters types
+ javadocCompletion.append('(');
+ if (method.parameters != null) {
+ boolean isVarargs = method.isVarargs();
+ for (int p=0, ln=method.parameters.length; p0) javadocCompletion.append(", "); //$NON-NLS-1$
+ TypeBinding argTypeBinding = method.parameters[p];
+ if (isVarargs && p == ln - 1) {
+ createVargsType(argTypeBinding, javadocCompletion);
+ } else {
+ createType(argTypeBinding, javadocCompletion);
+ }
+ }
+ }
+ javadocCompletion.append(')');
+ completion = javadocCompletion.toString().toCharArray();
+ }
+ } else {
+ // nothing to insert - do not want to replace the existing selector & arguments
+ if (!exactMatch) {
+ if (this.source != null
+ && this.source.length > this.endPosition
+ && this.source[this.endPosition] == '(')
+ completion = method.selector;
+ else
+ completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
+ } else {
+ if(prefixRequired && (this.source != null)) {
+ completion = CharOperation.subarray(this.source, this.startPosition, this.endPosition);
+ } else {
+ this.startPosition = this.endPosition;
+ }
+ }
+
+ if(prefixRequired || this.options.forceImplicitQualification){
+ char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
+ completion = CharOperation.concat(prefix,completion,'.');
+ }
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ if (methodName != null) relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+ relevance += computeRelevanceForExpectingType(method.returnType);
+ relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic());
+ relevance += computeRelevanceForQualification(prefixRequired);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+ if (onlyStaticMethods && this.insideQualifiedReference) {
+ relevance += computeRelevanceForInheritance(receiverType, method.declaringClass);
+ }
+ if (missingElements != null) {
+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems);
+ }
+
+ this.noProposal = false;
+ // Standard proposal
+ if(!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setName(method.selector);
+ proposal.setIsContructor(method.isConstructor());
+
+ if (missingElements != null) {
+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length];
+ for (int i = 0; i < missingElements.length; i++) {
+ subProposals[i] =
+ createRequiredTypeProposal(
+ missingElements[i],
+ missingElementsStarts[i],
+ missingElementsEnds[i],
+ relevance);
+ }
+ proposal.setRequiredProposals(subProposals);
+ }
+ proposal.setCompletion(completion);
+ proposal.setFlags(method.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Javadoc proposal
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_METHOD_REF)) {
+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = this.createProposal(CompletionProposal.JSDOC_METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setName(method.selector);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags(method.modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ this.startPosition = previousStartPosition;
+ }
+
+ methodsFound.addAll(newMethodsFound);
+ }
+
+ private void findLocalMethodsFromFavorites(
+ char[] methodName,
+ MethodBinding[] methods,
+ Scope scope,
+ ObjectVector methodsFound,
+ ReferenceBinding receiverType,
+ InvocationSite invocationSite,
+ Scope invocationScope) {
+
+ char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.');
+
+ int methodLength = methodName.length;
+
+ next : for (int f = methods.length; --f >= 0;) {
+ MethodBinding method = methods[f];
+
+ if (method.isDefaultAbstract()) continue next;
+
+ if (method.isConstructor()) continue next;
+
+ if (this.options.checkDeprecation &&
+ method.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(method.declaringClass))
+ continue next;
+
+ if (!method.isStatic()) continue next;
+
+ if (this.options.checkVisibility
+ && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+
+ if (methodLength > method.selector.length) continue next;
+
+ if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) {
+ continue next;
+ }
+
+ for (int i = methodsFound.size; --i >= 0;) {
+ Object[] other = (Object[]) methodsFound.elementAt(i);
+ MethodBinding otherMethod = (MethodBinding) other[0];
+
+ if (method == otherMethod) continue next;
+
+ if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
+ if (lookupEnvironment.methodVerifier().doesMethodOverride(otherMethod, method)) {
+ continue next;
+ }
+ }
+ }
+
+ boolean proposeStaticImport = !(this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5) &&
+ this.options.suggestStaticImport;
+
+ boolean isAlreadyImported = false;
+ if (!proposeStaticImport) {
+ if(!this.importCachesInitialized) {
+ this.initializeImportCaches();
+ }
+ for (int j = 0; j < this.importCacheCount; j++) {
+ char[][] importName = this.importsCache[j];
+ if(CharOperation.equals(receiverType.sourceName, importName[0])) {
+ if (!CharOperation.equals(typeName, importName[1])) {
+ continue next;
+ } else {
+ isAlreadyImported = true;
+ }
+ }
+ }
+ }
+
+ methodsFound.add(new Object[]{method, receiverType});
+
+ ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeWithSameErasure(method.declaringClass);
+ if (method.declaringClass != superTypeWithSameErasure) {
+ MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector);
+ for (int i = 0; i < otherMethods.length; i++) {
+ if(otherMethods[i].original() == method.original()) {
+ method = otherMethods[i];
+ }
+ }
+ }
+
+ int length = method.parameters.length;
+ char[][] parameterPackageNames = new char[length][];
+ char[][] parameterTypeNames = new char[length][];
+
+ for (int i = 0; i < length; i++) {
+ TypeBinding type = method.original().parameters[i];
+ parameterPackageNames[i] = type.qualifiedPackageName();
+ parameterTypeNames[i] = type.qualifiedSourceName();
+ }
+ char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
+
+ char[] completion = CharOperation.NO_CHAR;
+
+ int previousStartPosition = this.startPosition;
+
+ if (this.source != null
+ && this.source.length > this.endPosition
+ && this.source[this.endPosition] == '(') {
+ completion = method.selector;
+ } else {
+ completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ if (methodName != null) relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+ relevance += computeRelevanceForExpectingType(method.returnType);
+ relevance += computeRelevanceForStatic(true, method.isStatic());
+ relevance += computeRelevanceForQualification(true);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ CompilationUnitDeclaration cu = this.unitScope.referenceContext;
+ int importStart = cu.types[0].declarationSourceStart;
+ int importEnd = importStart;
+
+ this.noProposal = false;
+
+ if (!proposeStaticImport) {
+ if (isAlreadyImported) {
+ if (!isIgnored(CompletionProposal.METHOD_REF)) {
+ completion = CharOperation.concat(receiverType.sourceName, completion, '.');
+
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setName(method.selector);
+ proposal.setCompletion(completion);
+ proposal.setFlags(method.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ } else if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_IMPORT)) {
+ completion = CharOperation.concat(receiverType.sourceName, completion, '.');
+
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setName(method.selector);
+ proposal.setCompletion(completion);
+ proposal.setFlags(method.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+
+ char[] typeImportCompletion = createImportCharArray(typeName, false, false);
+
+ CompletionProposal typeImportProposal = this.createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition);
+ typeImportProposal.nameLookup = this.nameEnvironment.nameLookup;
+ typeImportProposal.completionEngine = this;
+ char[] packageName = receiverType.qualifiedPackageName();
+ typeImportProposal.setDeclarationSignature(packageName);
+ typeImportProposal.setSignature(getSignature(receiverType));
+ typeImportProposal.setPackageName(packageName);
+ typeImportProposal.setTypeName(receiverType.qualifiedSourceName());
+ typeImportProposal.setCompletion(typeImportCompletion);
+ typeImportProposal.setFlags(receiverType.modifiers);
+ typeImportProposal.setAdditionalFlags(CompletionFlags.Default);
+ typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
+ typeImportProposal.setRelevance(relevance);
+
+ proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal});
+
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ } else {
+ if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.METHOD_IMPORT)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setName(method.selector);
+ proposal.setCompletion(completion);
+ proposal.setFlags(method.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+
+ char[] methodImportCompletion = createImportCharArray(CharOperation.concat(typeName, method.selector, '.'), true, false);
+
+ CompletionProposal methodImportProposal = this.createProposal(CompletionProposal.METHOD_IMPORT, this.actualCompletionPosition);
+ methodImportProposal.setDeclarationSignature(getSignature(method.declaringClass));
+ methodImportProposal.setSignature(getSignature(method));
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ methodImportProposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ methodImportProposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ methodImportProposal.setParameterPackageNames(parameterPackageNames);
+ methodImportProposal.setParameterTypeNames(parameterTypeNames);
+ methodImportProposal.setPackageName(method.returnType.qualifiedPackageName());
+ methodImportProposal.setTypeName(method.returnType.qualifiedSourceName());
+ methodImportProposal.setName(method.selector);
+ methodImportProposal.setCompletion(methodImportCompletion);
+ methodImportProposal.setFlags(method.modifiers);
+ methodImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset);
+ methodImportProposal.setRelevance(relevance);
+ if(parameterNames != null) methodImportProposal.setParameterNames(parameterNames);
+
+ proposal.setRequiredProposals(new CompletionProposal[]{methodImportProposal});
+
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+
+ this.startPosition = previousStartPosition;
+ }
+ }
+
+ private CompletionProposal createRequiredTypeProposal(Binding binding, int start, int end, int relevance) {
+ CompletionProposal proposal = null;
+ if (binding instanceof ReferenceBinding) {
+ ReferenceBinding typeBinding = (ReferenceBinding) binding;
+
+ char[] packageName = typeBinding.qualifiedPackageName();
+ char[] typeName = typeBinding.qualifiedSourceName();
+ char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
+
+ proposal = this.createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+ proposal.nameLookup = this.nameEnvironment.nameLookup;
+ proposal.completionEngine = this;
+ proposal.setDeclarationSignature(packageName);
+ proposal.setSignature(getSignature(typeBinding));
+ proposal.setPackageName(packageName);
+ proposal.setTypeName(typeName);
+ proposal.setCompletion(fullyQualifiedName);
+ proposal.setFlags(typeBinding.modifiers);
+ proposal.setReplaceRange(start - this.offset, end - this.offset);
+ proposal.setRelevance(relevance);
+ } else if (binding instanceof PackageBinding) {
+ PackageBinding packageBinding = (PackageBinding) binding;
+
+ char[] packageName = CharOperation.concatWith(packageBinding.compoundName, '.');
+
+ proposal = this.createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(packageName);
+ proposal.setPackageName(packageName);
+ proposal.setCompletion(packageName);
+ proposal.setReplaceRange(start - this.offset, end - this.offset);
+ proposal.setRelevance(relevance);
+ }
+ return proposal;
+ }
+
+ int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
+ if (this.options.camelCaseMatch) {
+ if(CharOperation.equals(token, proposalName, true /* do not ignore case */)) {
+ return R_CASE + R_EXACT_NAME;
+ } else if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) {
+ return R_CASE;
+ } else if (CharOperation.camelCaseMatch(token, proposalName)){
+ return R_CAMEL_CASE;
+ } else if(CharOperation.equals(token, proposalName, false /* ignore case */)) {
+ return R_EXACT_NAME;
+ }
+ } else if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) {
+ if(CharOperation.equals(token, proposalName, true /* do not ignore case */)) {
+ return R_CASE + R_EXACT_NAME;
+ } else {
+ return R_CASE;
+ }
+ } else if(CharOperation.equals(token, proposalName, false /* ignore case */)) {
+ return R_EXACT_NAME;
+ }
+ return 0;
+ }
+ private int computeRelevanceForClass(){
+ if(this.assistNodeIsClass) {
+ return R_CLASS;
+ }
+ return 0;
+ }
+ private int computeRelevanceForMissingElements(boolean hasProblems) {
+ if (!hasProblems) {
+ return R_NO_PROBLEMS;
+ }
+ return 0;
+ }
+ int computeRelevanceForQualification(boolean prefixRequired) {
+ if(!prefixRequired && !this.insideQualifiedReference) {
+ return R_UNQUALIFIED;
+ }
+
+ if(prefixRequired && this.insideQualifiedReference) {
+ return R_QUALIFIED;
+ }
+ return 0;
+ }
+ int computeRelevanceForRestrictions(int accessRuleKind) {
+ if(accessRuleKind == IAccessRule.K_ACCESSIBLE) {
+ return R_NON_RESTRICTED;
+ }
+ return 0;
+ }
+ private int computeRelevanceForStatic(boolean onlyStatic, boolean isStatic) {
+ if(this.insideQualifiedReference && !onlyStatic && !isStatic) {
+ return R_NON_STATIC;
+ }
+ return 0;
+ }
+ private int computeRelevanceForException(){
+ if (this.assistNodeIsException) {
+ return R_EXCEPTION;
+ }
+ return 0;
+ }
+ private int computeRelevanceForException(char[] proposalName){
+
+ if((this.assistNodeIsException || (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) != 0 )&&
+ (CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
+ CharOperation.match(ERROR_PATTERN, proposalName, false))) {
+ return R_EXCEPTION;
+ }
+ return 0;
+ }
+ private int computeRelevanceForExpectingType(TypeBinding proposalType){
+ if(this.expectedTypes != null && proposalType != null) {
+ for (int i = 0; i <= this.expectedTypesPtr; i++) {
+ int relevance = R_EXPECTED_TYPE;
+ if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) &&
+ CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) {
+ relevance = R_EXACT_EXPECTED_TYPE;
+ }
+ if((this.expectedTypesFilter & SUBTYPE) != 0
+ && proposalType.isCompatibleWith(this.expectedTypes[i])) {
+ return relevance;
+ }
+ if((this.expectedTypesFilter & SUPERTYPE) != 0
+ && this.expectedTypes[i].isCompatibleWith(proposalType)) {
+ return relevance;
+ }
+ }
+ }
+ return 0;
+ }
+ private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){
+ if(this.expectedTypes != null) {
+ for (int i = 0; i <= this.expectedTypesPtr; i++) {
+ if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), packageName) &&
+ CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), typeName)) {
+ return R_EXACT_EXPECTED_TYPE;
+ }
+ }
+ if(this.hasJavaLangObjectAsExpectedType) {
+ return R_EXPECTED_TYPE;
+ }
+ }
+ return 0;
+ }
+
+ private int computeRelevanceForInheritance(ReferenceBinding receiverType, ReferenceBinding declaringClass) {
+ if (receiverType == declaringClass) return R_NON_INHERITED;
+ return 0;
+ }
+
+ int computeRelevanceForInterestingProposal(){
+ return computeRelevanceForInterestingProposal(null);
+ }
+ private int computeRelevanceForInterestingProposal(Binding binding){
+ if(this.uninterestingBindings != null) {
+ for (int i = 0; i <= this.uninterestingBindingsPtr; i++) {
+ if(this.uninterestingBindings[i] == binding) {
+ return 0;
+ }
+ }
+ }
+ return R_INTERESTING;
+ }
+ private void computeUninterestingBindings(ASTNode parent, Scope scope){
+ if(parent instanceof LocalDeclaration) {
+ addUninterestingBindings(((LocalDeclaration)parent).binding);
+ } else if (parent instanceof FieldDeclaration) {
+ addUninterestingBindings(((FieldDeclaration)parent).binding);
+ }
+ }
+
+ private void findLabels(char[] label, char[][] choices) {
+ if(choices == null || choices.length == 0) return;
+
+ int length = label.length;
+ for (int i = 0; i < choices.length; i++) {
+ if (length <= choices[i].length
+ && CharOperation.prefixEquals(label, choices[i], false /* ignore case */
+ )){
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(label, choices[i]);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.LABEL_REF, this.actualCompletionPosition);
+ proposal.setName(choices[i]);
+ proposal.setCompletion(choices[i]);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ }
+
+ // Helper method for findMethods(char[], FunctionBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
+ private void findLocalMethodDeclarations(
+ char[] methodName,
+ MethodBinding[] methods,
+ Scope scope,
+ ObjectVector methodsFound,
+ // boolean noVoidReturnType, how do you know?
+ boolean exactMatch,
+ ReferenceBinding receiverType) {
+
+ ObjectVector newMethodsFound = new ObjectVector();
+ // Inherited methods which are hidden by subclasses are filtered out
+ // No visibility checks can be performed without the scope & invocationSite
+ int methodLength = methodName.length;
+ next : for (int f = methods.length; --f >= 0;) {
+
+ MethodBinding method = methods[f];
+
+ if (method.isDefaultAbstract()) continue next;
+
+ if (method.isConstructor()) continue next;
+
+ if (method.isFinal()) {
+ newMethodsFound.add(method);
+ continue next;
+ }
+
+ if (this.options.checkDeprecation &&
+ method.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(method.declaringClass))
+ continue next;
+
+ // if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
+ if(method.isStatic()) continue next;
+
+ if (!method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
+
+ if (exactMatch) {
+ if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
+ ))
+ continue next;
+
+ } else {
+
+ if (methodLength > method.selector.length)
+ continue next;
+
+ if (!CharOperation.prefixEquals(methodName, method.selector, false/* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector)))
+ continue next;
+ }
+
+ for (int i = methodsFound.size; --i >= 0;) {
+ MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
+ if (method == otherMethod)
+ continue next;
+
+ if (CharOperation.equals(method.selector, otherMethod.selector, true)
+ && lookupEnvironment.methodVerifier().doesMethodOverride(otherMethod, method)) {
+ continue next;
+ }
+ }
+
+ newMethodsFound.add(method);
+
+ int length = method.parameters.length;
+ char[][] parameterPackageNames = new char[length][];
+ char[][] parameterFullTypeNames = new char[length][];
+
+ for (int i = 0; i < length; i++) {
+ TypeBinding type = method.parameters[i];
+ parameterPackageNames[i] = type.qualifiedPackageName();
+ parameterFullTypeNames[i] = type.qualifiedSourceName();
+ }
+
+ char[][] parameterNames = findMethodParameterNames(method, parameterFullTypeNames);
+
+ StringBuffer completion = new StringBuffer(10);
+ if (!exactMatch) {
+ createMethod(method, parameterPackageNames, parameterFullTypeNames, parameterNames, completion);
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+ relevance += R_METHOD_OVERIDE;
+ if(method.isAbstract()) relevance += R_ABSTRACT_METHOD;
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE);
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.METHOD_DECLARATION, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(method.declaringClass));
+ proposal.setDeclarationKey(method.declaringClass.computeUniqueKey());
+ proposal.setSignature(getSignature(method));
+ MethodBinding original = method.original();
+ if(original != method) {
+ proposal.setOriginalSignature(getSignature(original));
+ }
+ proposal.setKey(method.computeUniqueKey());
+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName());
+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName());
+ proposal.setParameterPackageNames(parameterPackageNames);
+ proposal.setParameterTypeNames(parameterFullTypeNames);
+ proposal.setPackageName(method.returnType.qualifiedPackageName());
+ proposal.setTypeName(method.returnType.qualifiedSourceName());
+ proposal.setCompletion(completion.toString().toCharArray());
+ proposal.setName(method.selector);
+ proposal.setFlags(method.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(parameterNames != null) proposal.setParameterNames(parameterNames);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ methodsFound.addAll(newMethodsFound);
+ }
+
+ private void createType(TypeBinding type, StringBuffer completion) {
+ if (type.isBaseType()) {
+ completion.append(type.sourceName());
+ } else if (type.isArrayType()) {
+ createType(type.leafComponentType(), completion);
+ int dim = type.dimensions();
+ for (int i = 0; i < dim; i++) {
+ completion.append('[');
+ completion.append(']');
+ }
+ } else {
+ char[] packageName = type.qualifiedPackageName();
+ char[] typeName = type.qualifiedSourceName();
+ if(mustQualifyType(
+ packageName,
+ type.sourceName(),
+ type.isMemberType() ? type.enclosingType().qualifiedSourceName() : null,
+ ((ReferenceBinding)type).modifiers)) {
+ completion.append(CharOperation.concat(packageName, typeName,'.'));
+ } else {
+ completion.append(type.sourceName());
+ }
+ }
+ }
+
+ private void createVargsType(TypeBinding type, StringBuffer completion) {
+ if (type.isArrayType()) {
+ createType(type.leafComponentType(), completion);
+ int dim = type.dimensions() - 1;
+ for (int i = 0; i < dim; i++) {
+ completion.append('[');
+ completion.append(']');
+ }
+ completion.append(VARARGS);
+ } else {
+ createType(type, completion);
+ }
+ }
+ private char[] createImportCharArray(char[] importedElement, boolean isStatic, boolean onDemand) {
+ char[] result = IMPORT;
+ if (isStatic) {
+ result = CharOperation.concat(result, STATIC, ' ');
+ }
+ result = CharOperation.concat(result, importedElement, ' ');
+ if (onDemand) {
+ result = CharOperation.concat(result, ON_DEMAND);
+ }
+ return CharOperation.concat(result, IMPORT_END);
+ }
+ private void createMethod(MethodBinding method, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, StringBuffer completion) {
+ //// Modifiers
+ // flush uninteresting modifiers
+ int insertedModifiers = method.modifiers & ~(ClassFileConstants.AccNative | ClassFileConstants.AccAbstract);
+ if(insertedModifiers != ClassFileConstants.AccDefault){
+ ASTNode.printModifiers(insertedModifiers, completion);
+ }
+
+ //// Return type
+ createType(method.returnType, completion);
+ completion.append(' ');
+
+ //// Selector
+ completion.append(method.selector);
+
+ completion.append('(');
+
+ ////Parameters
+ TypeBinding[] parameterTypes = method.parameters;
+ int length = parameterTypes.length;
+ for (int i = 0; i < length; i++) {
+ if(i != 0) {
+ completion.append(',');
+ completion.append(' ');
+ }
+ createType(parameterTypes[i], completion);
+ completion.append(' ');
+ if(parameterNames != null){
+ completion.append(parameterNames[i]);
+ } else {
+ completion.append('%');
+ }
+ }
+
+ completion.append(')');
+ }
+
+ private boolean isIgnored(int kind, boolean missingTypes) {
+ return this.requestor.isIgnored(kind) ||
+ (missingTypes && !this.requestor.isAllowingRequiredProposals(kind, CompletionProposal.TYPE_REF));
+ }
+
+ private boolean isIgnored(int kind) {
+ return this.requestor.isIgnored(kind);
+ }
+
+ private boolean isIgnored(int kind, int requiredProposalKind) {
+ return this.requestor.isIgnored(kind) ||
+ !this.requestor.isAllowingRequiredProposals(kind, requiredProposalKind);
+ }
+
+ private void findMethods(
+ char[] selector,
+ TypeBinding[] typeArgTypes,
+ TypeBinding[] argTypes,
+ ReferenceBinding receiverType,
+ Scope scope,
+ ObjectVector methodsFound,
+ boolean onlyStaticMethods,
+ boolean exactMatch,
+ boolean isCompletingDeclaration,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ boolean implicitCall,
+ boolean superCall,
+ boolean canBePrefixed,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean missingElementsHaveProblems) {
+
+ boolean notInJavadoc = this.assistNodeInJavadoc == 0;
+ if (selector == null && notInJavadoc) {
+ return;
+ }
+
+ if(isCompletingDeclaration) {
+ MethodBinding[] methods = receiverType.availableMethods();
+ if (methods != null){
+ for (int i = 0; i < methods.length; i++) {
+ if(!methods[i].isDefaultAbstract()) {
+ methodsFound.add(methods[i]);
+ }
+ }
+ }
+ }
+
+ ReferenceBinding currentType = receiverType;
+ if (notInJavadoc) {
+ if (isCompletingDeclaration){
+
+ currentType = receiverType.superclass();
+ }
+ }
+ while (currentType != null) {
+
+ MethodBinding[] methods = currentType.availableMethods();
+ if (methods != null) {
+ if (isCompletingDeclaration){
+ findLocalMethodDeclarations(
+ selector,
+ methods,
+ scope,
+ methodsFound,
+ exactMatch,
+ receiverType);
+ } else{
+ findLocalMethods(
+ selector,
+ typeArgTypes,
+ argTypes,
+ methods,
+ methods.length,
+ scope,
+ methodsFound,
+ onlyStaticMethods,
+ exactMatch,
+ receiverType,
+ invocationSite,
+ invocationScope,
+ implicitCall,
+ superCall,
+ canBePrefixed,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds,
+ missingElementsHaveProblems);
+ }
+ }
+
+ currentType = currentType.superclass();
+
+ }
+ }
+ private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
+ TypeBinding erasure = method.declaringClass;
+ if(!(erasure instanceof ReferenceBinding)) return null;
+
+ char[][] parameterNames = null;
+
+ int length = parameterTypeNames.length;
+
+ if (length == 0){
+ return CharOperation.NO_CHAR_CHAR;
+ }
+ // look into the corresponding unit if it is available
+ if (erasure instanceof SourceTypeBinding){
+ SourceTypeBinding sourceType = (SourceTypeBinding) erasure;
+
+ if (sourceType instanceof CompilationUnitBinding){
+ CompilationUnitDeclaration parsedType;
+
+ if ((parsedType = ((CompilationUnitScope)sourceType.scope).referenceContext) != null){
+ AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method.original());
+
+ if(methodDecl == null && method.isConstructor()) {
+ //if its a constructor we know the return type is the type the method is defined on
+ InferredType type = parsedType.findInferredType(method.returnType.qualifiedSourceName());
+ if(type != null) {
+ InferredMethod infMethod = type.findMethod(method.selector, null);
+
+ if(infMethod.getFunctionDeclaration() instanceof AbstractMethodDeclaration) {
+ methodDecl = (AbstractMethodDeclaration)infMethod.getFunctionDeclaration();
+ }
+ }
+ }
+
+ if (methodDecl != null){
+ Argument[] arguments = methodDecl.arguments;
+ parameterNames = new char[length][];
+
+ for(int i = 0 ; i < length ; i++){
+ parameterNames[i] = arguments[i].name;
+ }
+ }
+ }
+ }
+ else if (sourceType instanceof MetatdataTypeBinding){
+ MetatdataTypeBinding metatdataTypeBinding=(MetatdataTypeBinding)sourceType;
+ ClassData classData = metatdataTypeBinding.getClassData();
+ Method meth = classData.getMethod(new String (method.selector));
+ if (meth != null){
+ int argLength=meth.parameters!=null ? meth.parameters.length : 0;
+ parameterNames = new char[argLength][];
+
+ for(int i = 0 ; i < argLength ; i++){
+ parameterNames[i] = meth.parameters[i].name.toCharArray();
+ }
+ }
+ }
+ else
+ if (sourceType.scope != null){
+ TypeDeclaration parsedType;
+ AbstractMethodDeclaration methodDecl = null;
+ if ((parsedType = ((ClassScope)sourceType.scope).referenceContext) != null)
+ methodDecl = parsedType.declarationOf(method.original());
+ else if ( ((ClassScope)sourceType.scope).inferredType != null)
+ methodDecl = (AbstractMethodDeclaration) ((ClassScope)sourceType.scope).inferredType.declarationOf(method.original());
+
+ if (methodDecl != null){
+ Argument[] arguments = methodDecl.arguments;
+ parameterNames = new char[length][];
+
+ for(int i = 0 ; i < length ; i++){
+ parameterNames[i] = arguments[i].name;
+ }
+ }
+ }
+ }
+ // look into the model
+ if(parameterNames == null){
+
+ ReferenceBinding bindingType = (ReferenceBinding)erasure;
+
+ char[] compoundName = CharOperation.concatWith(bindingType.compoundName, '.');
+ Object type = this.typeCache.get(compoundName);
+
+ ISourceType sourceType = null;
+ if(type != null) {
+ if(type instanceof ISourceType) {
+ sourceType = (ISourceType) type;
+ }
+ } else {
+ NameEnvironmentAnswer answer = this.nameEnvironment.findType(bindingType.compoundName,this);
+ if(answer != null && answer.isSourceType()) {
+ sourceType = answer.getSourceTypes()[0];
+ this.typeCache.put(compoundName, sourceType);
+ }
+ }
+
+ if(sourceType != null) {
+ IType typeHandle = ((SourceTypeElementInfo) sourceType).getHandle();
+
+ String[] parameterTypeSignatures = new String[length];
+ for (int i = 0; i < length; i++) {
+ parameterTypeSignatures[i] = Signature.createTypeSignature(parameterTypeNames[i], false);
+ }
+ IFunction searchedMethod = typeHandle.getFunction(String.valueOf(method.selector), parameterTypeSignatures);
+ IFunction[] foundMethods = typeHandle.findMethods(searchedMethod);
+
+ if(foundMethods != null) {
+ int len = foundMethods.length;
+ if(len == 1) {
+ try {
+ SourceMethod sourceMethod = (SourceMethod) foundMethods[0];
+ parameterNames = ((SourceMethodElementInfo) sourceMethod.getElementInfo()).getArgumentNames();
+ } catch (JavaScriptModelException e) {
+ // method doesn't exist: ignore
+ }
+ }
+ }
+ }
+ }
+ return parameterNames;
+ }
+
+ private void findNestedTypes(
+ char[] typeName,
+ SourceTypeBinding currentType,
+ Scope scope,
+ boolean proposeAllMemberTypes,
+ ObjectVector typesFound) {
+ if (typeName == null)
+ return;
+
+ int typeLength = typeName.length;
+
+ SourceTypeBinding nextTypeToIgnore = null;
+ while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (scope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ case Scope.BLOCK_SCOPE :
+ BlockScope blockScope = (BlockScope) scope;
+
+ next : for (int i = 0, length = blockScope.subscopeCount; i < length; i++) {
+
+ if (blockScope.subscopes[i] instanceof ClassScope) {
+ SourceTypeBinding localType =
+ ((ClassScope) blockScope.subscopes[i]).getReferenceBinding();
+
+ if (!localType.isAnonymousType()) {
+ if (this.isForbidden(localType))
+ continue next;
+
+ if (typeLength > localType.sourceName.length)
+ continue next;
+ if (!CharOperation.prefixEquals(typeName, localType.sourceName, false/* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, localType.sourceName)))
+ continue next;
+
+ for (int j = typesFound.size; --j >= 0;) {
+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j);
+
+ if (localType == otherType)
+ continue next;
+ }
+
+ if(this.assistNodeIsClass) {
+ if(!localType.isClass()) continue next;
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName);
+ relevance += computeRelevanceForExpectingType(localType);
+ relevance += computeRelevanceForException(localType.sourceName);
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForQualification(false);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for nested type
+
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ createTypeProposal(localType, localType.sourceName, IAccessRule.K_ACCESSIBLE, localType.sourceName, relevance);
+ }
+ }
+ }
+ }
+ break;
+
+ case Scope.CLASS_SCOPE :
+ SourceTypeBinding enclosingSourceType = scope.enclosingSourceType();
+ findMemberTypes(typeName, enclosingSourceType, scope, currentType, false, false, false, false, proposeAllMemberTypes, nextTypeToIgnore, typesFound);
+ nextTypeToIgnore = enclosingSourceType;
+ if (typeLength == 0)
+ return; // do not search outside the class scope if no prefix was provided
+ break;
+
+ case Scope.COMPILATION_UNIT_SCOPE :
+ return;
+ }
+ scope = scope.parent;
+ }
+ }
+
+ private void findTypesAndPackages(char[] token, Scope scope, ObjectVector typesFound) {
+
+ if (token == null)
+ return;
+
+ boolean proposeType =
+ !this.requestor.isIgnored(CompletionProposal.TYPE_REF) ||
+ ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0);
+
+ boolean proposeAllMemberTypes = !this.assistNodeIsConstructor;
+
+ boolean proposeConstructor =
+ this.assistNodeIsConstructor &&
+ (!isIgnored(CompletionProposal.CONSTRUCTOR_INVOCATION, CompletionProposal.TYPE_REF));
+
+
+ if ((proposeType || proposeConstructor) && scope.enclosingSourceType() != null) {
+ findNestedTypes(token, scope.enclosingSourceType(), scope, proposeAllMemberTypes, typesFound);
+ }
+
+ boolean isEmptyPrefix = token.length == 0;
+
+ if ((proposeType || proposeConstructor) && this.unitScope != null) {
+
+ ReferenceBinding outerInvocationType = scope.enclosingSourceType();
+ if(outerInvocationType != null) {
+ ReferenceBinding temp = outerInvocationType.enclosingType();
+ while(temp != null) {
+ outerInvocationType = temp;
+ temp = temp.enclosingType();
+ }
+ }
+
+ int typeLength = token.length;
+ SourceTypeBinding[] types = this.unitScope.topLevelTypes;
+
+ next : for (int i = 0, length = types.length; i < length; i++) {
+ SourceTypeBinding sourceType = types[i];
+
+ if(isForbidden(sourceType)) continue next;
+
+ //hide anonymous types
+ if( sourceType.isAnonymousType() ) {
+ continue next;
+ }
+
+ if(proposeAllMemberTypes &&
+ sourceType != outerInvocationType) {
+ findSubMemberTypes(
+ token,
+ sourceType,
+ scope,
+ scope.enclosingSourceType(),
+ false,
+ false,
+ false,
+ typesFound);
+ }
+
+ if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue next;
+ if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue next;
+
+ if (typeLength > sourceType.sourceName.length) continue next;
+
+ int index = CharOperation.lastIndexOf('.', sourceType.sourceName);
+ if (index > 0) {
+// char[] pkg = CharOperation.subarray(sourceType.sourceName, 0, index);
+ char[] simpleName = CharOperation.subarray(sourceType.sourceName, index+1, sourceType.sourceName.length);
+
+ if (!CharOperation.prefixEquals(token, simpleName, false) && !CharOperation.prefixEquals(token, sourceType.sourceName, false)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, simpleName))) {
+
+ continue;
+ }
+
+ } else if (!CharOperation.prefixEquals(token, sourceType.sourceName, false)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) {
+
+ continue;
+ }
+
+ for (int j = typesFound.size; --j >= 0;) {
+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j);
+
+ if (sourceType == otherType) continue next;
+ }
+
+ this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this);
+
+ if(this.assistNodeIsClass) {
+ if(!sourceType.isClass()) continue next;
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
+ relevance += computeRelevanceForExpectingType(sourceType);
+ relevance += computeRelevanceForQualification(false);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for type in the current unit
+
+ if(sourceType.isClass()){
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException(sourceType.sourceName);
+ }
+ this.noProposal = false;
+ if(proposeType && !this.assistNodeIsConstructor) {
+ char[] typeName = sourceType.sourceName();
+ createTypeProposal(
+ sourceType,
+ typeName,
+ IAccessRule.K_ACCESSIBLE,
+ typeName,
+ relevance);
+ }
+
+ if (proposeConstructor) {
+ findConstructors(
+ sourceType,
+ null,
+ scope,
+ FakeInvocationSite,
+ false);
+ }
+ }
+ }
+
+ if (isEmptyPrefix) {
+ if (!proposeConstructor) {
+ findTypesFromExpectedTypes(token, scope, typesFound, proposeType, proposeConstructor);
+ }
+ } else {
+ if (proposeConstructor) {
+ //search index for constructors that match
+ this.nameEnvironment.findConstructorDeclarations(
+ token,
+ this);
+ acceptConstructors();
+ } else if (proposeType) {
+ int searchFor = IJavaScriptSearchConstants.TYPE;
+ if(this.assistNodeIsClass) {
+ searchFor = IJavaScriptSearchConstants.CLASS;
+ }
+
+ this.nameEnvironment.findTypes(
+ token,
+ proposeAllMemberTypes,
+ this.options.camelCaseMatch,
+ searchFor,
+ this);
+ acceptTypes(scope);
+ }
+ if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
+ this.nameEnvironment.findPackages(token, this);
+ }
+ }
+ }
+
+ private void findTypesAndSubpackages(
+ char[] token,
+ PackageBinding packageBinding,
+ Scope scope) {
+
+ boolean proposeType =
+ !this.requestor.isIgnored(CompletionProposal.TYPE_REF) ||
+ ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_TYPE_REF));
+
+ char[] qualifiedName =
+ CharOperation.concatWith(packageBinding.compoundName, token, '.');
+
+ if (token == null || token.length == 0) {
+ int length = qualifiedName.length;
+ System.arraycopy(
+ qualifiedName,
+ 0,
+ qualifiedName = new char[length + 1],
+ 0,
+ length);
+ qualifiedName[length] = '.';
+ }
+
+ this.qualifiedCompletionToken = qualifiedName;
+
+ if (proposeType && this.unitScope != null) {
+ int typeLength = qualifiedName.length;
+ SourceTypeBinding[] types = this.unitScope.topLevelTypes;
+
+ for (int i = 0, length = types.length; i < length; i++) {
+ SourceTypeBinding sourceType = types[i];
+
+ char[] qualifiedSourceTypeName = CharOperation.concatWith(sourceType.compoundName, '.');
+
+ if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue;
+ if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue;
+ if (typeLength > qualifiedSourceTypeName.length) continue;
+ if (!(packageBinding == sourceType.getPackage())) continue;
+
+ if (!CharOperation.prefixEquals(qualifiedName, qualifiedSourceTypeName, false)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue;
+
+ if (this.options.checkDeprecation &&
+ sourceType.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(sourceType))
+ continue;
+
+ int accessibility = IAccessRule.K_ACCESSIBLE;
+ if(sourceType.hasRestrictedAccess()) {
+ AccessRestriction accessRestriction = lookupEnvironment.getAccessRestriction(sourceType);
+ if(accessRestriction != null) {
+ switch (accessRestriction.getProblemId()) {
+ case IProblem.ForbiddenReference:
+ if (this.options.checkForbiddenReference) {
+ continue;
+ }
+ accessibility = IAccessRule.K_NON_ACCESSIBLE;
+ break;
+ case IProblem.DiscouragedReference:
+ if (this.options.checkDiscouragedReference) {
+ continue;
+ }
+ accessibility = IAccessRule.K_DISCOURAGED;
+ break;
+ }
+ }
+ }
+
+ this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this);
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(qualifiedName, qualifiedSourceTypeName);
+ relevance += computeRelevanceForExpectingType(sourceType);
+ relevance += computeRelevanceForQualification(false);
+ relevance += computeRelevanceForRestrictions(accessibility);
+
+ if (sourceType.isClass()) {
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException(sourceType.sourceName);
+ }
+ this.noProposal = false;
+ if(proposeType) {
+ char[] typeName = sourceType.sourceName();
+ createTypeProposal(sourceType, typeName, IAccessRule.K_ACCESSIBLE, typeName, relevance);
+ }
+ }
+ }
+
+ if(proposeType) {
+ int searchFor = IJavaScriptSearchConstants.TYPE;
+ if(this.assistNodeIsClass) {
+ searchFor = IJavaScriptSearchConstants.CLASS;
+ }
+ this.nameEnvironment.findTypes(
+ qualifiedName,
+ false,
+ this.options.camelCaseMatch,
+ searchFor,
+ this);
+ acceptTypes(scope);
+ }
+ }
+
+ private void findVariablesAndMethods(
+ char[] token,
+ Scope scope,
+ InvocationSite invocationSite,
+ Scope invocationScope,
+ boolean insideTypeAnnotation,
+ boolean insideAnnotationAttribute) {
+
+ if (token == null)
+ return;
+
+ // Should local variables hide fields from the receiver type or any of its enclosing types?
+ // we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod
+
+ boolean staticsOnly = false;
+ // need to know if we're in a static context (or inside a constructor)
+ int tokenLength = token.length;
+
+ ObjectVector localsFound = new ObjectVector();
+ ObjectVector fieldsFound = new ObjectVector();
+ ObjectVector methodsFound = new ObjectVector();
+
+ Scope currentScope = scope;
+
+ if (!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
+ done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+ LocalVariableBinding arguments = null;
+ switch (currentScope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+ MethodScope methodScope = (MethodScope) currentScope;
+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+ arguments = methodScope.argumentsBinding;
+
+ case Scope.BLOCK_SCOPE :
+ case Scope.COMPILATION_UNIT_SCOPE :
+ BlockScope blockScope = (BlockScope) currentScope;
+ LocalVariableBinding[] localBindings = null;
+ if(arguments != null) {
+ localBindings = new LocalVariableBinding[blockScope.locals.length + 1];
+ System.arraycopy(blockScope.locals, 0, localBindings, 1, blockScope.locals.length);
+ localBindings[0] = arguments;
+ } else {
+ localBindings = blockScope.locals;
+ }
+
+ next : for (int i = 0, length = localBindings.length; i < length; i++) {
+ LocalVariableBinding local = localBindings[i];
+
+ if (local == null)
+ break next;
+
+
+ if (tokenLength > local.name.length)
+ continue next;
+
+ if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, local.name)))
+ continue next;
+
+ if (local.isSecret())
+ continue next;
+
+ for (int f = 0; f < localsFound.size; f++) {
+ LocalVariableBinding otherLocal =
+ (LocalVariableBinding) localsFound.elementAt(f);
+ if (CharOperation.equals(otherLocal.name, local.name, true))
+ continue next;
+ }
+ localsFound.add(local);
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal(local);
+ relevance += computeRelevanceForCaseMatching(token, local.name);
+ relevance += computeRelevanceForExpectingType(local.type);
+ relevance += computeRelevanceForQualification(false);
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) {
+ CompletionProposal proposal = this.createProposal(CompletionProposal.LOCAL_VARIABLE_REF, this.actualCompletionPosition);
+ proposal.setSignature(
+ local.type == null
+ ? createTypeSignature(
+ CharOperation.NO_CHAR,
+ local.declaration.getTypeName().toCharArray())
+ : getSignature(local.type));
+ if(local.type == null) {
+ //proposal.setPackageName(null);
+ proposal.setTypeName(local.declaration.getTypeName().toCharArray());
+ } else {
+ proposal.setPackageName(local.type.qualifiedPackageName());
+ proposal.setTypeName(local.type.qualifiedSourceName());
+ }
+ proposal.setName(local.name);
+ proposal.setCompletion(local.name);
+ proposal.setFlags(local.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ if(local.declaration != null) {
+ proposal.setLocalDeclarationSourceRange(local.declaration.sourceStart, local.declaration.sourceEnd);
+ } else {
+ if(local.declaringScope != null) {
+ LocalVariableBinding[] bindings = local.declaringScope.locals;
+ for(int j = 0; j < bindings.length; j++) {
+ if(bindings[j] != null && CharOperation.equals(bindings[j].name, local.name) &&
+ bindings[j].declaration != null) {
+ proposal.setLocalDeclarationSourceRange(bindings[j].declaration.sourceStart, bindings[j].declaration.sourceEnd);
+ }
+ }
+ }
+ }
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+
+ if (currentScope.kind==Scope.COMPILATION_UNIT_SCOPE )
+ break done1;
+ else
+ break;
+ }
+ currentScope = currentScope.parent;
+ }
+ }
+
+ boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF);
+ boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF);
+
+ staticsOnly = false;
+ currentScope = scope;
+
+ if(proposeField || proposeMethod) {
+ done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (currentScope.kind) {
+ case Scope.METHOD_SCOPE :
+ // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+ MethodScope methodScope = (MethodScope) currentScope;
+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+ if (proposeMethod && methodScope.numberMethods>0)
+ {
+ findLocalMethods(
+ token,
+ null,
+ null,
+ methodScope.methods,
+ methodScope.numberMethods,
+ currentScope,
+ methodsFound,
+ false,
+ false,
+ null,
+ invocationSite,
+ invocationScope,
+ true,
+ false,
+ true,
+ null,
+ null,
+ null,
+ false);
+
+
+ }
+ break;
+// case Scope.CLASS_SCOPE :
+ case Scope.COMPILATION_UNIT_SCOPE :
+ CompilationUnitScope compilationUnitScope = (CompilationUnitScope) currentScope;
+// ClassScope classScope = (ClassScope) currentScope;
+ SourceTypeBinding enclosingType = compilationUnitScope.enclosingCompilationUnit();
+ /* if (tokenLength == 0) { // only search inside the type itself if no prefix was provided
+ findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly);
+ findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false);
+ break done;
+ } else { */
+ if(!insideTypeAnnotation) {
+ if(proposeField) {
+ findFields(
+ token,
+ enclosingType,
+ compilationUnitScope,
+ fieldsFound,
+ localsFound,
+ staticsOnly,
+ invocationSite,
+ invocationScope,
+ true,
+ true,
+ null,
+ null,
+ null,
+ false);
+ }
+ if(proposeMethod && !insideAnnotationAttribute) {
+ findMethods(
+ token,
+ null,
+ null,
+ enclosingType,
+ compilationUnitScope,
+ methodsFound,
+ staticsOnly,
+ false,
+ false,
+ invocationSite,
+ invocationScope,
+ true,
+ false,
+ true,
+ null,
+ null,
+ null,
+ false);
+ }
+ }
+ staticsOnly |= enclosingType.isStatic();
+ insideTypeAnnotation = false;
+ // }
+// break;
+
+// case Scope.COMPILATION_UNIT_SCOPE :
+ break done2;
+ }
+ currentScope = currentScope.parent;
+ }
+
+ if (this.assistNodeInJavadoc == 0) {
+ // search in favorites import
+ findFieldsAndMethodsFromFavorites(
+ token,
+ scope,
+ invocationSite,
+ invocationScope,
+ localsFound,
+ fieldsFound,
+ methodsFound);
+ }
+
+ //propose methods from environment if token length is not 0
+ if (proposeMethod && token.length > 0)
+ {
+ this.nameEnvironment.findBindings(
+ token,
+ Binding.METHOD,
+ this.options.camelCaseMatch,
+ this);
+ acceptBindings(token,false,false);
+ }
+
+ //propose fields from environment if token length is not 0
+ if (proposeField && token.length > 0)
+ {
+ this.nameEnvironment.findBindings(
+ token,
+ Binding.VARIABLE,
+ this.options.camelCaseMatch,
+ this);
+ acceptBindings(token,false,false);
+ }
+ }
+ }
+ private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) {
+ final TypeReference type = variable.type;
+ if(type != null &&
+ type.resolvedType != null &&
+ type.resolvedType.problemId() == ProblemReasons.NoError){
+
+ final ArrayList proposedNames = new ArrayList();
+
+ UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor =
+ new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() {
+ public void acceptName(char[] name) {
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(completionToken, name);
+ relevance += R_NAME_FIRST_PREFIX;
+ relevance += R_NAME_FIRST_SUFFIX;
+ relevance += R_NAME_LESS_NEW_CHARACTERS;
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name
+
+ // accept result
+ CompletionEngine.this.noProposal = false;
+ if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
+ CompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition);
+ proposal.setSignature(getSignature(type.resolvedType));
+ proposal.setPackageName(type.resolvedType.qualifiedPackageName());
+ proposal.setTypeName(type.resolvedType.qualifiedSourceName());
+ proposal.setName(name);
+ proposal.setCompletion(name);
+ //proposal.setFlags(Flags.AccDefault);
+ proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset);
+ proposal.setRelevance(relevance);
+ CompletionEngine.this.requestor.accept(proposal);
+ if(DEBUG) {
+ CompletionEngine.this.printDebug(proposal);
+ }
+ }
+ proposedNames.add(name);
+ }
+ };
+
+ ReferenceContext referenceContext = scope.referenceContext();
+ if (referenceContext instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext;
+
+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
+ nameFinder.find(
+ completionToken,
+ md,
+ variable.declarationSourceEnd + 1,
+ discouragedNames,
+ nameRequestor);
+ } else if (referenceContext instanceof TypeDeclaration) {
+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ if (fields != null) {
+ done : for (int i = 0; i < fields.length; i++) {
+ if (fields[i] instanceof Initializer) {
+ Initializer initializer = (Initializer) fields[i];
+ if (initializer.bodyStart <= variable.sourceStart &&
+ variable.sourceStart < initializer.bodyEnd) {
+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
+ nameFinder.find(
+ completionToken,
+ initializer,
+ typeDeclaration.scope,
+ variable.declarationSourceEnd + 1,
+ discouragedNames,
+ nameRequestor);
+ break done;
+ }
+ }
+ }
+ }
+ }
+
+ int proposedNamesCount = proposedNames.size();
+ if (proposedNamesCount > 0) {
+ return (char[][])proposedNames.toArray(new char[proposedNamesCount][]);
+ }
+ }
+
+ return null;
+ }
+
+ private char[][] findUnresolvedReferenceAfter(int from, BlockScope scope, final char[][] discouragedNames) {
+ final ArrayList proposedNames = new ArrayList();
+
+ UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor =
+ new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() {
+ public void acceptName(char[] name) {
+ CompletionEngine.this.acceptUnresolvedName(name);
+ proposedNames.add(name);
+ }
+ };
+
+ ReferenceContext referenceContext = scope.referenceContext();
+ if (referenceContext instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext;
+
+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
+ nameFinder.findAfter(
+ completionToken,
+ md.scope,
+ md.scope.classScope(),
+ from,
+ md.bodyEnd,
+ discouragedNames,
+ nameRequestor);
+ } else if (referenceContext instanceof TypeDeclaration) {
+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ if (fields != null) {
+ done : for (int i = 0; i < fields.length; i++) {
+ if (fields[i] instanceof Initializer) {
+ Initializer initializer = (Initializer) fields[i];
+ if (initializer.block.sourceStart <= from &&
+ from < initializer.bodyEnd) {
+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
+ nameFinder.findAfter(
+ completionToken,
+ typeDeclaration.scope,
+ typeDeclaration.scope,
+ from,
+ initializer.bodyEnd,
+ discouragedNames,
+ nameRequestor);
+ break done;
+ }
+ }
+ }
+ }
+ }
+
+ int proposedNamesCount = proposedNames.size();
+ if (proposedNamesCount > 0) {
+ return (char[][])proposedNames.toArray(new char[proposedNamesCount][]);
+ }
+
+ return null;
+ }
+
+ private void findUnresolvedReference(int completedNameStart, int completedNameEnd, BlockScope scope, char[][] discouragedNames) {
+ char[][] foundNames = findUnresolvedReferenceBefore(completedNameStart - 1, completedNameEnd, scope, discouragedNames);
+ if (foundNames != null && foundNames.length > 1) {
+ int discouragedNamesLength = discouragedNames.length;
+ int foundNamesLength = foundNames.length;
+ int newLength = discouragedNamesLength + foundNamesLength;
+ System.arraycopy(discouragedNames, 0, discouragedNames = new char[newLength][], 0, discouragedNamesLength);
+ System.arraycopy(foundNames, 0, discouragedNames, discouragedNamesLength, foundNamesLength);
+ }
+ findUnresolvedReferenceAfter(completedNameEnd + 1, scope, discouragedNames);
+ }
+
+ private char[][] findUnresolvedReferenceBefore(int recordTo, int parseTo, BlockScope scope, final char[][] discouragedNames) {
+ final ArrayList proposedNames = new ArrayList();
+
+ UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor =
+ new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() {
+ public void acceptName(char[] name) {
+ CompletionEngine.this.acceptUnresolvedName(name);
+ proposedNames.add(name);
+ }
+ };
+
+ BlockScope upperScope = scope;
+ while (upperScope.enclosingMethodScope() != null && upperScope.enclosingMethodScope()!=upperScope) {
+ upperScope = upperScope.enclosingMethodScope();
+ }
+ if (upperScope.enclosingMethodScope()==null)
+ upperScope=scope.compilationUnitScope();
+
+ ReferenceContext referenceContext = upperScope.referenceContext();
+ if (referenceContext instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext;
+
+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
+ nameFinder.findBefore(
+ completionToken,
+ md.scope,
+ md.scope.classScope(),
+ md.bodyStart,
+ recordTo,
+ parseTo,
+ discouragedNames,
+ nameRequestor);
+ } else if (referenceContext instanceof TypeDeclaration) {
+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext;
+
+
+ done : {
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ if (fields != null) {
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i] instanceof Initializer) {
+ Initializer initializer = (Initializer) fields[i];
+ if (initializer.block.sourceStart <= recordTo &&
+ recordTo < initializer.bodyEnd) {
+
+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this);
+ nameFinder.findBefore(
+ completionToken,
+ typeDeclaration.scope,
+ typeDeclaration.scope,
+ initializer.block.sourceStart,
+ recordTo,
+ parseTo,
+ discouragedNames,
+ nameRequestor);
+ break done;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int proposedNamesCount = proposedNames.size();
+ if (proposedNamesCount > 0) {
+ return (char[][])proposedNames.toArray(new char[proposedNamesCount][]);
+ }
+
+ return null;
+ }
+
+ // Helper method for private void findVariableNames(char[] name, TypeReference type )
+ private void findVariableName(
+ char[] token,
+ char[] qualifiedPackageName,
+ char[] qualifiedSourceName,
+ char[] sourceName,
+ final TypeBinding typeBinding,
+ char[][] discouragedNames,
+ final char[][] forbiddenNames,
+ int dim,
+ int kind,
+ int modifiers){
+
+ if(sourceName == null || sourceName.length == 0)
+ return;
+
+ // compute variable name for non base type
+ final char[] displayName;
+ if (dim > 0){
+ int l = qualifiedSourceName.length;
+ displayName = new char[l+(2*dim)];
+ System.arraycopy(qualifiedSourceName, 0, displayName, 0, l);
+ for(int i = 0; i < dim; i++){
+ displayName[l+(i*2)] = '[';
+ displayName[l+(i*2)+1] = ']';
+ }
+ } else {
+ displayName = qualifiedSourceName;
+ }
+
+ final char[] t = token;
+ final char[] q = qualifiedPackageName;
+ INamingRequestor namingRequestor = new INamingRequestor() {
+ public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters) {
+ accept(
+ name,
+ (isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX) + (isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX),
+ reusedCharacters);
+ }
+
+ public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters) {
+ accept(name, isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX, reusedCharacters);
+ }
+
+ public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters) {
+ accept(name, isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX, reusedCharacters);
+ }
+
+ public void acceptNameWithoutPrefixAndSuffix(char[] name,int reusedCharacters) {
+ accept(name, 0, reusedCharacters);
+ }
+ void accept(char[] name, int prefixAndSuffixRelevance, int reusedCharacters){
+ int l = forbiddenNames == null ? 0 : forbiddenNames.length;
+ for (int i = 0; i < l; i++) {
+ if (CharOperation.equals(forbiddenNames[i], name, false)) return;
+ }
+
+ if (CharOperation.prefixEquals(t, name, false)) {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(t, name);
+ relevance += prefixAndSuffixRelevance;
+ if(reusedCharacters > 0) relevance += R_NAME_LESS_NEW_CHARACTERS;
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name
+
+ // accept result
+ CompletionEngine.this.noProposal = false;
+ if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
+ CompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition);
+ proposal.setSignature(getSignature(typeBinding));
+ proposal.setPackageName(q);
+ proposal.setTypeName(displayName);
+ proposal.setName(name);
+ proposal.setCompletion(name);
+ //proposal.setFlags(Flags.AccDefault);
+ proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset);
+ proposal.setRelevance(relevance);
+ CompletionEngine.this.requestor.accept(proposal);
+ if(DEBUG) {
+ CompletionEngine.this.printDebug(proposal);
+ }
+ }
+ }
+ }
+ };
+
+ switch (kind) {
+ case FIELD :
+ InternalNamingConventions.suggestFieldNames(
+ this.javaProject,
+ qualifiedPackageName,
+ qualifiedSourceName,
+ dim,
+ modifiers,
+ token,
+ discouragedNames,
+ namingRequestor);
+ break;
+ case LOCAL :
+ InternalNamingConventions.suggestLocalVariableNames(
+ this.javaProject,
+ qualifiedPackageName,
+ qualifiedSourceName,
+ dim,
+ token,
+ discouragedNames,
+ namingRequestor);
+ break;
+ case ARGUMENT :
+ InternalNamingConventions.suggestArgumentNames(
+ this.javaProject,
+ qualifiedPackageName,
+ qualifiedSourceName,
+ dim,
+ token,
+ discouragedNames,
+ namingRequestor);
+ break;
+ }
+ }
+
+ private void findVariableNames(char[] name, TypeReference type , char[][] discouragedNames, char[][] forbiddenNames, int kind, int modifiers){
+
+ if(type != null &&
+ type.resolvedType != null &&
+ type.resolvedType.problemId() == ProblemReasons.NoError){
+ TypeBinding tb = type.resolvedType;
+ findVariableName(
+ name,
+ tb.leafComponentType().qualifiedPackageName(),
+ tb.leafComponentType().qualifiedSourceName(),
+ tb.leafComponentType().sourceName(),
+ tb,
+ discouragedNames,
+ forbiddenNames,
+ type.dimensions(),
+ kind,
+ modifiers);
+ }/* else {
+ char[][] typeName = type.getTypeName();
+ findVariableName(
+ name,
+ NoChar,
+ CharOperation.concatWith(typeName, '.'),
+ typeName[typeName.length - 1],
+ excludeNames,
+ type.dimensions());
+ }*/
+ }
+
+ private ImportBinding[] getFavoriteReferenceBindings(Scope scope) {
+ if (this.favoriteReferenceBindings != null) return this.favoriteReferenceBindings;
+
+ String[] favoriteReferences = this.requestor.getFavoriteReferences();
+
+ if (favoriteReferences == null || favoriteReferences.length == 0) return null;
+
+ ImportBinding[] resolvedImports = new ImportBinding[favoriteReferences.length];
+
+ int count = 0;
+ next : for (int i = 0; i < favoriteReferences.length; i++) {
+ String favoriteReference = favoriteReferences[i];
+
+ int length;
+ if (favoriteReference == null || (length = favoriteReference.length()) == 0) continue next;
+
+ boolean onDemand = favoriteReference.charAt(length - 1) == '*';
+
+ char[][] compoundName = CharOperation.splitOn('.', favoriteReference.toCharArray());
+ if (onDemand) {
+ compoundName = CharOperation.subarray(compoundName, 0, compoundName.length - 1);
+ }
+
+ // remove duplicate and conflicting
+ for (int j = 0; j < count; j++) {
+ ImportReference f = resolvedImports[j].reference;
+
+ if (CharOperation.equals(f.tokens, compoundName)) continue next;
+
+ if (!onDemand && ((f.bits & ASTNode.OnDemand) == 0)) {
+ if (CharOperation.equals(f.tokens[f.tokens.length - 1], compoundName[compoundName.length - 1]))
+ continue next;
+ }
+ }
+
+ boolean isStatic = true;
+
+ ImportReference importReference =
+ new ImportReference(
+ compoundName,
+ new long[compoundName.length],
+ onDemand);
+
+ Binding importBinding = this.unitScope.findImport(compoundName, onDemand);
+
+ if (!importBinding.isValidBinding()) {
+ continue next;
+ }
+
+ if (importBinding instanceof PackageBinding) {
+ continue next;
+ }
+
+ resolvedImports[count++] =
+ new ImportBinding(compoundName, onDemand, importBinding, importReference);
+ }
+
+ if (resolvedImports.length > count)
+ System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[count], 0, count);
+
+ return this.favoriteReferenceBindings = resolvedImports;
+ }
+
+ public AssistParser getParser() {
+
+ return this.parser;
+ }
+
+ protected void reset() {
+
+ super.reset();
+ this.knownPkgs = new HashtableOfObject(10);
+ this.knownTypes = new HashtableOfObject(10);
+ }
+
+ private void setSourceRange(int start, int end) {
+ this.setSourceRange(start, end, true);
+ }
+
+ private void setSourceRange(int start, int end, boolean emptyTokenAdjstment) {
+ this.startPosition = start;
+ if (emptyTokenAdjstment) {
+ int endOfEmptyToken = ((CompletionScanner) this.parser.scanner).endOfEmptyToken;
+ if (end == 0) {
+ this.endPosition = 0;
+ }
+ else {
+ this.endPosition = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1;
+ }
+ }
+ else {
+ this.endPosition = end + 1;
+ }
+ }
+ private char[][] computeAlreadyDefinedName(
+ BlockScope scope,
+ InvocationSite invocationSite) {
+ ArrayList result = new ArrayList();
+
+ boolean staticsOnly = false;
+
+ Scope currentScope = scope;
+
+ done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+ switch (currentScope.kind) {
+
+ case Scope.METHOD_SCOPE :
+ // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+ MethodScope methodScope = (MethodScope) currentScope;
+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+
+ case Scope.BLOCK_SCOPE :
+ BlockScope blockScope = (BlockScope) currentScope;
+
+ next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
+ LocalVariableBinding local = blockScope.locals[i];
+
+ if (local == null)
+ break next;
+
+ if (local.isSecret())
+ continue next;
+
+ result.add(local.name);
+ }
+ break;
+
+ case Scope.CLASS_SCOPE :
+ ClassScope classScope = (ClassScope) currentScope;
+ SourceTypeBinding enclosingType = classScope.getReferenceBinding();
+ computeAlreadyDefinedName(
+ enclosingType,
+ classScope,
+ staticsOnly,
+ invocationSite,
+ result);
+ staticsOnly |= enclosingType.isStatic();
+ break;
+
+ case Scope.COMPILATION_UNIT_SCOPE :
+ break done1;
+ }
+ currentScope = currentScope.parent;
+ }
+
+ if (result.size() == 0) return CharOperation.NO_CHAR_CHAR;
+
+ return (char[][])result.toArray(new char[result.size()][]);
+ }
+
+ private void computeAlreadyDefinedName(
+ SourceTypeBinding receiverType,
+ ClassScope scope,
+ boolean onlyStaticFields,
+ InvocationSite invocationSite,
+ ArrayList result) {
+
+ ReferenceBinding currentType = receiverType;
+ do {
+ FieldBinding[] fields = currentType.availableFields();
+ if(fields != null && fields.length > 0) {
+ computeAlreadyDefinedName(
+ fields,
+ scope,
+ onlyStaticFields,
+ receiverType,
+ invocationSite,
+ result);
+ }
+ currentType = currentType.superclass();
+ } while ( currentType != null);
+ }
+
+ private void computeAlreadyDefinedName(
+ FieldBinding[] fields,
+ Scope scope,
+ boolean onlyStaticFields,
+ ReferenceBinding receiverType,
+ InvocationSite invocationSite,
+ ArrayList result) {
+
+ next : for (int f = fields.length; --f >= 0;) {
+ FieldBinding field = fields[f];
+
+ if (onlyStaticFields && !field.isStatic()) continue next;
+
+ if (!field.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+
+ result.add(field.name);
+ }
+ }
+
+ int computeBaseRelevance(){
+ return R_DEFAULT;
+ }
+ int computeRelevanceForResolution(){
+ return computeRelevanceForResolution(true);
+ }
+ int computeRelevanceForResolution(boolean isResolved){
+ if (isResolved) {
+ return R_RESOLVED;
+ }
+ return 0;
+ }
+ private void computeExpectedTypes(ASTNode parent, ASTNode node, Scope scope){
+
+ // default filter
+ this.expectedTypesFilter = SUBTYPE;
+ this.hasJavaLangObjectAsExpectedType = false;
+
+ // find types from parent
+ if(parent instanceof AbstractVariableDeclaration) {
+ AbstractVariableDeclaration variable = (AbstractVariableDeclaration)parent;
+ TypeBinding binding = variable.getTypeBinding();
+ if(binding != null) {
+ if(!(variable.initialization instanceof ArrayInitializer)) {
+ addExpectedType(binding, scope);
+ }
+ }
+ } else if(parent instanceof Assignment) {
+ TypeBinding binding = ((Assignment)parent).lhs.resolvedType;
+ if(binding != null) {
+ addExpectedType(binding, scope);
+ }
+ } else if(parent instanceof ReturnStatement) {
+ if(scope.methodScope().referenceContext instanceof AbstractMethodDeclaration) {
+ MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding;
+ TypeBinding binding = methodBinding == null ? null : methodBinding.returnType;
+ if(binding != null) {
+ addExpectedType(binding, scope);
+ }
+ }
+ } else if(parent instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) parent;
+
+ if(messageSend.actualReceiverType instanceof ReferenceBinding) {
+ ReferenceBinding binding = (ReferenceBinding)messageSend.actualReceiverType;
+ boolean isStatic = messageSend.receiver!=null && messageSend.receiver.isTypeReference();
+
+ while(binding != null) {
+ computeExpectedTypesForMessageSend(
+ binding,
+ messageSend.selector,
+ messageSend.arguments,
+ (ReferenceBinding)messageSend.actualReceiverType,
+ scope,
+ messageSend,
+ isStatic);
+ binding = binding.superclass();
+ }
+ }
+ } else if(parent instanceof AllocationExpression) {
+ AllocationExpression allocationExpression = (AllocationExpression) parent;
+
+ ReferenceBinding binding =null;
+ if (allocationExpression.type!=null)
+ binding=(ReferenceBinding)allocationExpression.type.resolvedType;
+ else
+ if (allocationExpression.member.resolvedType instanceof ReferenceBinding)
+ binding=(ReferenceBinding)allocationExpression.member.resolvedType;
+
+
+ if(binding != null) {
+ computeExpectedTypesForAllocationExpression(
+ binding,
+ allocationExpression.arguments,
+ scope,
+ allocationExpression);
+ }
+ } else if(parent instanceof OperatorExpression) {
+ int operator = (parent.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
+ if(parent instanceof ConditionalExpression) {
+ // for future use
+ } else if(parent instanceof InstanceOfExpression) {
+ InstanceOfExpression e = (InstanceOfExpression) parent;
+ TypeBinding binding = e.expression.resolvedType;
+ if(binding != null){
+ addExpectedType(binding, scope);
+ this.expectedTypesFilter = SUBTYPE | SUPERTYPE;
+ }
+ } else if(parent instanceof BinaryExpression) {
+ switch(operator) {
+ case OperatorIds.PLUS :
+ addExpectedType(TypeBinding.ANY, scope);
+ addExpectedType(scope.getJavaLangString(), scope);
+ break;
+ case OperatorIds.AND_AND :
+ case OperatorIds.OR_OR :
+ case OperatorIds.XOR :
+ addExpectedType(TypeBinding.BOOLEAN, scope);
+ break;
+ default :
+ addExpectedType(TypeBinding.ANY, scope);
+ break;
+ }
+ BinaryExpression binaryExpression = (BinaryExpression) parent;
+ if(operator == OperatorIds.LESS) {
+ if(binaryExpression.left instanceof SingleNameReference){
+ SingleNameReference name = (SingleNameReference) binaryExpression.left;
+ Binding b = scope.getBinding(name.token, Binding.VARIABLE | Binding.TYPE, name, false);
+ }
+ }
+ } else if(parent instanceof UnaryExpression) {
+ switch(operator) {
+ case OperatorIds.NOT :
+ addExpectedType(TypeBinding.BOOLEAN, scope);
+ break;
+ case OperatorIds.TWIDDLE :
+ addExpectedType(TypeBinding.SHORT, scope);
+ addExpectedType(TypeBinding.INT, scope);
+ addExpectedType(TypeBinding.LONG, scope);
+ addExpectedType(TypeBinding.CHAR, scope);
+ break;
+ case OperatorIds.PLUS :
+ case OperatorIds.MINUS :
+ case OperatorIds.PLUS_PLUS :
+ case OperatorIds.MINUS_MINUS :
+ addExpectedType(TypeBinding.SHORT, scope);
+ addExpectedType(TypeBinding.INT, scope);
+ addExpectedType(TypeBinding.LONG, scope);
+ addExpectedType(TypeBinding.FLOAT, scope);
+ addExpectedType(TypeBinding.DOUBLE, scope);
+ addExpectedType(TypeBinding.CHAR, scope);
+ break;
+ }
+ }
+ } else if(parent instanceof ArrayReference) {
+ addExpectedType(TypeBinding.SHORT, scope);
+ addExpectedType(TypeBinding.INT, scope);
+ addExpectedType(TypeBinding.LONG, scope);
+ } else if (parent instanceof TryStatement) {
+ boolean isException = false;
+ if (node instanceof CompletionOnSingleTypeReference) {
+ isException = ((CompletionOnSingleTypeReference)node).isException();
+ } else if (node instanceof CompletionOnQualifiedTypeReference) {
+ isException = ((CompletionOnQualifiedTypeReference)node).isException();
+ }
+ if (isException) {
+ ThrownExceptionFinder thrownExceptionFinder = new ThrownExceptionFinder();
+ ReferenceBinding[] bindings = thrownExceptionFinder.find((TryStatement) parent, (BlockScope)scope);
+ if (bindings != null && bindings.length > 0) {
+ for (int i = 0; i < bindings.length; i++) {
+ addExpectedType(bindings[i], scope);
+ }
+ this.expectedTypesFilter = SUPERTYPE;
+ }
+ }
+
+ // Expected types for javadoc
+ }
+
+ if(this.expectedTypesPtr + 1 != this.expectedTypes.length) {
+ System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[this.expectedTypesPtr + 1], 0, this.expectedTypesPtr + 1);
+ }
+ }
+
+ private void computeExpectedTypesForAllocationExpression(
+ ReferenceBinding binding,
+ Expression[] arguments,
+ Scope scope,
+ InvocationSite invocationSite) {
+
+ MethodBinding[] methods = binding.availableMethods();
+ nextMethod : for (int i = 0; i < methods.length; i++) {
+ MethodBinding method = methods[i];
+
+ if (!method.isConstructor()) continue nextMethod;
+
+ if (this.options.checkVisibility && !method.canBeSeenBy(invocationSite, scope)) continue nextMethod;
+
+ TypeBinding[] parameters = method.parameters;
+ if(parameters.length < arguments.length)
+ continue nextMethod;
+
+ int length = arguments.length - 1;
+
+ for (int j = 0; j < length; j++) {
+ Expression argument = arguments[j];
+ TypeBinding argType = argument.resolvedType;
+ if(argType != null && !argType.isCompatibleWith(parameters[j]))
+ continue nextMethod;
+ }
+
+ TypeBinding expectedType = method.parameters[arguments.length - 1];
+ if(expectedType != null) {
+ addExpectedType(expectedType, scope);
+ }
+ }
+ }
+
+ private void computeExpectedTypesForMessageSend(
+ ReferenceBinding binding,
+ char[] selector,
+ Expression[] arguments,
+ ReferenceBinding receiverType,
+ Scope scope,
+ InvocationSite invocationSite,
+ boolean isStatic) {
+
+ MethodBinding[] methods = binding.availableMethods();
+ nextMethod : for (int i = 0; i < methods.length; i++) {
+ MethodBinding method = methods[i];
+
+ if (method.isDefaultAbstract()) continue nextMethod;
+
+ if (method.isConstructor()) continue nextMethod;
+
+ if (isStatic && !method.isStatic()) continue nextMethod;
+
+ if (this.options.checkVisibility && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue nextMethod;
+
+ if(!CharOperation.equals(method.selector, selector)) continue nextMethod;
+
+ TypeBinding[] parameters = method.parameters;
+ if(parameters.length < arguments.length)
+ continue nextMethod;
+
+ int length = arguments.length - 1;
+
+ for (int j = 0; j < length; j++) {
+ Expression argument = arguments[j];
+ TypeBinding argType = argument.resolvedType;
+ if(argType != null && !argType.isCompatibleWith(parameters[j]))
+ continue nextMethod;
+ }
+
+ TypeBinding expectedType = method.parameters[arguments.length - 1];
+ if(expectedType != null) {
+ addExpectedType(expectedType, scope);
+ }
+ }
+ }
+ private void addExpectedType(TypeBinding type, Scope scope){
+ if (type == null || !type.isValidBinding()) return;
+
+ int length = this.expectedTypes.length;
+ if (++this.expectedTypesPtr >= length)
+ System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[length * 2], 0, length);
+ this.expectedTypes[this.expectedTypesPtr] = type;
+
+ if(type == scope.getJavaLangObject()) {
+ this.hasJavaLangObjectAsExpectedType = true;
+ }
+ }
+ private void addForbiddenBindings(Binding binding){
+ if (binding == null) return;
+
+ int length = this.forbbidenBindings.length;
+ if (++this.forbbidenBindingsPtr >= length)
+ System.arraycopy(this.forbbidenBindings, 0, this.forbbidenBindings = new Binding[length * 2], 0, length);
+ this.forbbidenBindings[this.forbbidenBindingsPtr] = binding;
+ }
+ private void addUninterestingBindings(Binding binding){
+ if (binding == null) return;
+
+ int length = this.uninterestingBindings.length;
+ if (++this.uninterestingBindingsPtr >= length)
+ System.arraycopy(this.uninterestingBindings, 0, this.uninterestingBindings = new Binding[length * 2], 0, length);
+ this.uninterestingBindings[this.uninterestingBindingsPtr] = binding;
+ }
+
+ private Scope computeForbiddenBindings(ASTNode astNode, ASTNode astNodeParent, Scope scope) {
+ this.forbbidenBindingsFilter = NONE;
+ if(scope instanceof ClassScope) {
+ TypeDeclaration typeDeclaration = ((ClassScope)scope).referenceContext;
+ if(typeDeclaration.superclass == astNode) {
+ this.addForbiddenBindings(typeDeclaration.binding);
+ return scope.parent;
+ }
+ } else {
+ if (astNodeParent != null && astNodeParent instanceof TryStatement) {
+ boolean isException = false;
+ if (astNode instanceof CompletionOnSingleTypeReference) {
+ isException = ((CompletionOnSingleTypeReference)astNode).isException();
+ } else if (astNode instanceof CompletionOnQualifiedTypeReference) {
+ isException = ((CompletionOnQualifiedTypeReference)astNode).isException();
+ }
+ if (isException) {
+ Argument[] catchArguments = ((TryStatement) astNodeParent).catchArguments;
+ int length = catchArguments == null ? 0 : catchArguments.length;
+ for (int i = 0; i < length; i++) {
+ TypeBinding caughtException = catchArguments[i].type.resolvedType;
+ if (caughtException != null) {
+ this.addForbiddenBindings(caughtException);
+ this.knownTypes.put(CharOperation.concat(caughtException.qualifiedPackageName(), caughtException.qualifiedSourceName(), '.'), this);
+ }
+ }
+ this.forbbidenBindingsFilter = SUBTYPE;
+ }
+ }
+ }
+// else if(scope instanceof MethodScope) {
+// MethodScope methodScope = (MethodScope) scope;
+// if(methodScope.insideTypeAnnotation) {
+// return methodScope.parent.parent;
+// }
+// }
+ return scope;
+ }
+ private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){
+
+ StringBuffer completion = new StringBuffer(10);
+
+ if (isStatic) {
+ completion.append(declarationType.sourceName());
+
+ } else if (declarationType == invocationType) {
+ completion.append(THIS);
+
+ } else {
+
+ if (!declarationType.isNestedType()) {
+
+ completion.append(declarationType.sourceName());
+ completion.append('.');
+ completion.append(THIS);
+
+ } else if (!declarationType.isAnonymousType()) {
+
+ completion.append(declarationType.sourceName());
+ completion.append('.');
+ completion.append(THIS);
+
+ }
+ }
+
+ return completion.toString().toCharArray();
+ }
+
+ private void proposeNewMethod(char[] token, ReferenceBinding reference) {
+ if(!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) {
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for new method
+
+ CompletionProposal proposal = this.createProposal(CompletionProposal.POTENTIAL_METHOD_DECLARATION, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(getSignature(reference));
+ proposal.setSignature(
+ createMethodSignature(
+ CharOperation.NO_CHAR_CHAR,
+ CharOperation.NO_CHAR_CHAR,
+ CharOperation.NO_CHAR,
+ VOID));
+ proposal.setDeclarationPackageName(reference.qualifiedPackageName());
+ proposal.setDeclarationTypeName(reference.qualifiedSourceName());
+
+ //proposal.setPackageName(null);
+ proposal.setTypeName(VOID);
+ proposal.setName(token);
+ //proposal.setParameterPackageNames(null);
+ //proposal.setParameterTypeNames(null);
+ //proposal.setPackageName(null);
+ proposal.setCompletion(token);
+ proposal.setFlags(Flags.AccPublic);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+ private boolean isForbidden(Binding binding) {
+ for (int i = 0; i <= this.forbbidenBindingsPtr; i++) {
+ if(this.forbbidenBindings[i] == binding) {
+ return true;
+ }
+ if((this.forbbidenBindingsFilter & SUBTYPE) != 0) {
+ if (binding instanceof TypeBinding &&
+ this.forbbidenBindings[i] instanceof TypeBinding &&
+ ((TypeBinding)binding).isCompatibleWith((TypeBinding)this.forbbidenBindings[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ private boolean isValidParent(ASTNode parent, ASTNode node, Scope scope){
+ return true;
+ }
+
+ public static char[] createNonGenericTypeSignature(char[] qualifiedTypeName) {
+ return Signature.createCharArrayTypeSignature(qualifiedTypeName, true);
+ }
+ public static char[] createTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) {
+ char[] name = new char[qualifiedTypeName.length];
+ System.arraycopy(qualifiedTypeName, 0, name, 0, qualifiedTypeName.length);
+
+ int depth = 0;
+ int length = name.length;
+ for (int i = length -1; i >= 0; i--) {
+ switch (name[i]) {
+ case '.':
+ if (depth == 0 && name[i - 1] != '>') {
+ name[i] = '$';
+ }
+ break;
+ case '<':
+ depth--;
+ break;
+ case '>':
+ depth++;
+ break;
+ }
+ }
+ return Signature.createCharArrayTypeSignature(
+ CharOperation.concat(
+ qualifiedPackageName,
+ name, '.'), true);
+ }
+
+ public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnPackagename, char[] returnTypeName) {
+ char[] returnTypeSignature =
+ returnTypeName == null || returnTypeName.length == 0
+ ? Signature.createCharArrayTypeSignature(VOID, true)
+ : Signature.createCharArrayTypeSignature(
+ CharOperation.concat(
+ returnPackagename,
+ CharOperation.replaceOnCopy(returnTypeName, '.', '$'), '.'), true);
+
+ return createMethodSignature(
+ parameterPackageNames,
+ parameterTypeNames,
+ returnTypeSignature);
+ }
+
+ public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnTypeSignature) {
+ char[][] parameterTypeSignature = new char[parameterTypeNames.length][];
+ for (int i = 0; i < parameterTypeSignature.length; i++) {
+ parameterTypeSignature[i] =
+ Signature.createCharArrayTypeSignature(
+ CharOperation.concat(
+ parameterPackageNames[i],
+ CharOperation.replaceOnCopy(parameterTypeNames[i], '.', '$'), '.'), true);
+ }
+
+ return Signature.createMethodSignature(
+ parameterTypeSignature,
+ returnTypeSignature);
+ }
+
+ protected CompletionProposal createProposal(int kind, int completionOffset) {
+ CompletionProposal proposal = CompletionProposal.create(kind, completionOffset - this.offset);
+ proposal.nameLookup = this.nameEnvironment.nameLookup;
+ proposal.completionEngine = this;
+ return proposal;
+ }
+
+ /*
+ * Create a completion proposal for a type.
+ */
+ private void createTypeProposal(char[] packageName, char[] typeName, int modifiers, int accessibility, char[] completionName, int relevance) {
+
+ // Create standard type proposal
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset);
+ proposal.nameLookup = this.nameEnvironment.nameLookup;
+ proposal.completionEngine = this;
+ proposal.setDeclarationSignature(packageName);
+ proposal.setSignature(createNonGenericTypeSignature(typeName));
+ proposal.setPackageName(packageName);
+ proposal.setTypeName(typeName);
+ proposal.setCompletion(completionName);
+ proposal.setFlags(modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ proposal.setAccessibility(accessibility);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Create javadoc text proposal if necessary
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_TYPE_REF)) {
+ char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = CompletionProposal.create(CompletionProposal.JSDOC_TYPE_REF, this.actualCompletionPosition - this.offset);
+ proposal.nameLookup = this.nameEnvironment.nameLookup;
+ proposal.completionEngine = this;
+ proposal.setDeclarationSignature(packageName);
+ proposal.setSignature(createNonGenericTypeSignature(typeName));
+ proposal.setPackageName(packageName);
+ proposal.setTypeName(typeName);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags(modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ proposal.setAccessibility(accessibility);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+
+ /*
+ * Create a completion proposal for a member type.
+ */
+ private void createTypeProposal(ReferenceBinding refBinding, char[] typeName, int accessibility, char[] completionName, int relevance) {
+
+ // Create standard type proposal
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) {
+ CompletionProposal proposal = CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset);
+ proposal.nameLookup = this.nameEnvironment.nameLookup;
+ proposal.completionEngine = this;
+ proposal.setDeclarationSignature(refBinding.qualifiedPackageName());
+ proposal.setSignature(getSignature(refBinding));
+ proposal.setPackageName(refBinding.qualifiedPackageName());
+ proposal.setTypeName(typeName);
+ proposal.setCompletion(completionName);
+ proposal.setFlags(refBinding.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+
+ // Create javadoc text proposal if necessary
+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JSDOC_TYPE_REF)) {
+ char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK);
+ CompletionProposal proposal = CompletionProposal.create(CompletionProposal.JSDOC_TYPE_REF, this.actualCompletionPosition - this.offset);
+ proposal.nameLookup = this.nameEnvironment.nameLookup;
+ proposal.completionEngine = this;
+ proposal.setDeclarationSignature(refBinding.qualifiedPackageName());
+ proposal.setSignature(getSignature(refBinding));
+ proposal.setPackageName(refBinding.qualifiedPackageName());
+ proposal.setTypeName(typeName);
+ proposal.setCompletion(javadocCompletion);
+ proposal.setFlags(refBinding.modifiers);
+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition;
+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance+R_INLINE_TAG);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+
+ /**
+ * Returns completion string inserted inside a specified inline tag.
+ * @param completionName
+ * @return char[] Completion text inclunding specified inline tag
+ */
+ private char[] inlineTagCompletion(char[] completionName, char[] inlineTag) {
+ int tagLength= inlineTag.length;
+ int completionLength = completionName.length;
+ int inlineLength = 2+tagLength+1+completionLength+1;
+ char[] inlineCompletion = new char[inlineLength];
+ inlineCompletion[0] = '{';
+ inlineCompletion[1] = '@';
+ System.arraycopy(inlineTag, 0, inlineCompletion, 2, tagLength);
+ inlineCompletion[tagLength+2] = ' ';
+ System.arraycopy(completionName, 0, inlineCompletion, tagLength+3, completionLength);
+ // do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026)
+ //inlineCompletion[inlineLength-2] = ' ';
+ inlineCompletion[inlineLength-1] = '}';
+ return inlineCompletion;
+ }
+
+ protected void printDebug(CategorizedProblem error) {
+ if(CompletionEngine.DEBUG) {
+ System.out.print("COMPLETION - completionFailure("); //$NON-NLS-1$
+ System.out.print(error);
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ }
+
+ private void printDebugTab(int tab, StringBuffer buffer) {
+ for (int i = 0; i < tab; i++) {
+ buffer.append('\t');
+ }
+ }
+
+ protected void printDebug(CompletionProposal proposal){
+ StringBuffer buffer = new StringBuffer();
+ printDebug(proposal, 0, buffer);
+ System.out.println(buffer.toString());
+ }
+ private void printDebug(CompletionProposal proposal, int tab, StringBuffer buffer){
+ printDebugTab(tab, buffer);
+ buffer.append("COMPLETION - "); //$NON-NLS-1$
+ switch(proposal.getKind()) {
+ case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
+ buffer.append("ANONYMOUS_CLASS_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.FIELD_REF :
+ buffer.append("FIELD_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.KEYWORD :
+ buffer.append("KEYWORD"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.LABEL_REF :
+ buffer.append("LABEL_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.LOCAL_VARIABLE_REF :
+ buffer.append("LOCAL_VARIABLE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_DECLARATION :
+ buffer.append("FUNCTION_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_REF :
+ buffer.append("FUNCTION_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.PACKAGE_REF :
+ buffer.append("PACKAGE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.TYPE_REF :
+ buffer.append("TYPE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.VARIABLE_DECLARATION :
+ buffer.append("VARIABLE_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.POTENTIAL_METHOD_DECLARATION :
+ buffer.append("POTENTIAL_METHOD_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_NAME_REFERENCE :
+ buffer.append("METHOD_NAME_REFERENCE"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.FIELD_IMPORT :
+ buffer.append("FIELD_IMPORT"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_IMPORT :
+ buffer.append("METHOD_IMPORT"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.TYPE_IMPORT :
+ buffer.append("TYPE_IMPORT"); //$NON-NLS-1$
+ break;
+ default :
+ buffer.append("PROPOSAL"); //$NON-NLS-1$
+ break;
+
+ }
+
+ buffer.append("{\n");//$NON-NLS-1$
+ printDebugTab(tab, buffer);
+ buffer.append("\tCompletion[").append(proposal.getCompletion() == null ? "null".toCharArray() : proposal.getCompletion()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ printDebugTab(tab, buffer);
+ buffer.append("\tDeclarationSignature[").append(proposal.getDeclarationSignature() == null ? "null".toCharArray() : proposal.getDeclarationSignature()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ printDebugTab(tab, buffer);
+ buffer.append("\tDeclarationKey[").append(proposal.getDeclarationKey() == null ? "null".toCharArray() : proposal.getDeclarationKey()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ printDebugTab(tab, buffer);
+ buffer.append("\tSignature[").append(proposal.getSignature() == null ? "null".toCharArray() : proposal.getSignature()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ printDebugTab(tab, buffer);
+ buffer.append("\tKey[").append(proposal.getKey() == null ? "null".toCharArray() : proposal.getKey()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ printDebugTab(tab, buffer);
+ buffer.append("\tName[").append(proposal.getName() == null ? "null".toCharArray() : proposal.getName()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ printDebugTab(tab, buffer);
+ buffer.append("\tFlags[");//$NON-NLS-1$
+ int flags = proposal.getFlags();
+ buffer.append(Flags.toString(flags));
+ buffer.append("]\n"); //$NON-NLS-1$
+
+ CompletionProposal[] proposals = proposal.getRequiredProposals();
+ if(proposals != null) {
+ printDebugTab(tab, buffer);
+ buffer.append("\tRequiredProposals[");//$NON-NLS-1$
+ for (int i = 0; i < proposals.length; i++) {
+ buffer.append("\n"); //$NON-NLS-1$
+ printDebug(proposals[i], tab + 2, buffer);
+ }
+ printDebugTab(tab, buffer);
+ buffer.append("\n\t]\n"); //$NON-NLS-1$
+ }
+
+ printDebugTab(tab, buffer);
+ buffer.append("\tCompletionLocation[").append(proposal.getCompletionLocation()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ int start = proposal.getReplaceStart();
+ int end = proposal.getReplaceEnd();
+ printDebugTab(tab, buffer);
+ buffer.append("\tReplaceStart[").append(start).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append("-ReplaceEnd[").append(end).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (this.source != null) {
+ printDebugTab(tab, buffer);
+ buffer.append("\tReplacedText[").append(this.source, start, end-start).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ printDebugTab(tab, buffer);
+ buffer.append("\tTokenStart[").append(proposal.getTokenStart()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append("-TokenEnd[").append(proposal.getTokenEnd()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ printDebugTab(tab, buffer);
+ buffer.append("\tRelevance[").append(proposal.getRelevance()).append("]\n"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ printDebugTab(tab, buffer);
+ buffer.append("}\n");//$NON-NLS-1$
+ }
+
+ public CompilationUnitDeclaration doParse(ICompilationUnit unit, AccessRestriction accessRestriction) {
+ CompilationResult unitResult =
+ new CompilationResult(unit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ try {
+ Parser localParser = new Parser(this.problemReporter, this.compilerOptions.parseLiteralExpressionsAsConstants);
+ // fix for 309133
+ localParser.scanner.taskTags = null;
+
+ CompilationUnitDeclaration parsedUnit = localParser.parse(unit, unitResult);
+ localParser.inferTypes(parsedUnit,this.compilerOptions);
+ return parsedUnit;
+ } catch (AbortCompilationUnit e) {
+// // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+// // one requested further along to resolve sourceUnit.
+// if (unitResult.compilationUnit == sourceUnit) { // only report once
+// requestor.acceptResult(unitResult.tagAsAccepted());
+// } else {
+ throw e; // want to abort enclosing request to compile
+// }
+ }
+
+ }
+
+ public static char[] getSignature(Binding binding) {
+ char[] result = null;
+ if ((binding.kind() & Binding.TYPE) != 0 || (binding.kind() & Binding.COMPILATION_UNIT) != 0) {
+ TypeBinding typeBinding = (TypeBinding)binding;
+ result = typeBinding.signature();
+ // walk the supertypes if the type is anonymous to get a useful name
+ while (typeBinding != null && typeBinding.isAnonymousType()) {
+ // why not just use ReferenceBinding here?
+ if (typeBinding instanceof SourceTypeBinding)
+ typeBinding = ((SourceTypeBinding) typeBinding).superclass();
+ else if (typeBinding instanceof BinaryTypeBinding)
+ typeBinding = ((BinaryTypeBinding) typeBinding).superclass();
+ // must avoid endless loop
+ else
+ typeBinding = null;
+ }
+ if (typeBinding != null && typeBinding != binding)
+ result = typeBinding.signature();
+
+ if (result != null) {
+ if ( (binding.kind() & Binding.TYPE) != 0 )
+ result = CharOperation.replaceOnCopy(result, '/', '.');
+ }
+ } else {
+ result = Engine.getSignature(binding);
+ }
+
+ return result;
+ }
+
+ private char[] computeToken(FieldReference field) {
+ char[] currentToken = field.token;
+ boolean addDot = false;
+ if(currentToken != null && currentToken.length == 0)
+ addDot = true;
+ if(field.receiver != null) {
+ if(field.receiver instanceof SingleNameReference) {
+ currentToken = CharOperation.concat(((SingleNameReference)field.receiver).token, currentToken, '.');
+ } else if(field.receiver instanceof FieldReference) {
+ currentToken = CharOperation.concat(computeToken((FieldReference) field.receiver), currentToken, '.');
+ }
+ }
+ if(addDot)
+ currentToken = CharOperation.append(currentToken, '.');
+ return currentToken;
+ }
+
+
+ private void findTypesFromExpectedTypes(char[] token, Scope scope, ObjectVector typesFound, boolean proposeType, boolean proposeConstructor) {
+ if(this.expectedTypesPtr > -1) {
+ int typeLength = token == null ? 0 : token.length;
+
+ next : for (int i = 0; i <= this.expectedTypesPtr; i++) {
+
+ if(this.expectedTypes[i] instanceof ReferenceBinding) {
+ ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i];
+
+ if (typeLength > 0) {
+ if (typeLength > refBinding.sourceName.length) continue next;
+
+ if (!CharOperation.prefixEquals(token, refBinding.sourceName, false)
+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, refBinding.sourceName))) continue next;
+ }
+
+ if (this.options.checkDeprecation &&
+ refBinding.isViewedAsDeprecated() &&
+ !scope.isDefinedInSameUnit(refBinding))
+ continue next;
+
+ int accessibility = IAccessRule.K_ACCESSIBLE;
+ if(refBinding.hasRestrictedAccess()) {
+ AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding);
+ if(accessRestriction != null) {
+ switch (accessRestriction.getProblemId()) {
+ case IProblem.ForbiddenReference:
+ if (this.options.checkForbiddenReference) {
+ continue next;
+ }
+ accessibility = IAccessRule.K_NON_ACCESSIBLE;
+ break;
+ case IProblem.DiscouragedReference:
+ if (this.options.checkDiscouragedReference) {
+ continue next;
+ }
+ accessibility = IAccessRule.K_DISCOURAGED;
+ break;
+ }
+ }
+ }
+
+ for (int j = 0; j < typesFound.size(); j++) {
+ ReferenceBinding typeFound = (ReferenceBinding)typesFound.elementAt(j);
+ if (typeFound == refBinding) {
+ continue next;
+ }
+ }
+
+ typesFound.add(refBinding);
+
+ boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding);
+
+ // top level types of the current unit are already proposed.
+ if(!inSameUnit || (inSameUnit && refBinding.isMemberType())) {
+ char[] packageName = refBinding.qualifiedPackageName();
+ char[] typeName = refBinding.sourceName();
+ char[] completionName = typeName;
+
+ boolean isQualified = false;
+ if (!this.insideQualifiedReference && !refBinding.isMemberType()) {
+ if (mustQualifyType(packageName, typeName, null, refBinding.modifiers)) {
+ if (packageName == null || packageName.length == 0)
+ if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+ continue next; // ignore types from the default package from outside it
+ completionName = CharOperation.concat(packageName, typeName, '.');
+ isQualified = true;
+ }
+ }
+
+ if(this.assistNodeIsClass) {
+ if(!refBinding.isClass()) continue next;
+ }
+
+ int relevance = computeBaseRelevance();
+ relevance += computeRelevanceForResolution();
+ relevance += computeRelevanceForInterestingProposal();
+ relevance += computeRelevanceForCaseMatching(token, typeName);
+ relevance += computeRelevanceForExpectingType(refBinding);
+ relevance += computeRelevanceForQualification(isQualified);
+ relevance += computeRelevanceForRestrictions(accessibility);
+
+ if(refBinding.isClass()) {
+ relevance += computeRelevanceForClass();
+ relevance += computeRelevanceForException(typeName);
+ }
+
+ if (proposeType && !this.assistNodeIsConstructor) {
+ this.noProposal = false;
+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
+ CompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition);
+ proposal.setDeclarationSignature(packageName);
+ proposal.setSignature(getSignature(refBinding));
+ proposal.setPackageName(packageName);
+ proposal.setTypeName(typeName);
+ proposal.setCompletion(completionName);
+ proposal.setFlags(refBinding.modifiers);
+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+ proposal.setRelevance(relevance);
+ proposal.setAccessibility(accessibility);
+ this.requestor.accept(proposal);
+ if(DEBUG) {
+ this.printDebug(proposal);
+ }
+ }
+ }
+
+ if (proposeConstructor) {
+ findConstructors(
+ refBinding,
+ null,
+ scope,
+ FakeInvocationSite,
+ isQualified);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private char[] getResolvedSignature(char[][] parameterTypes, char[] fullyQualifiedTypeName, int parameterCount, Scope scope) {
+ char[][] cn = CharOperation.splitOn('.', fullyQualifiedTypeName);
+
+ TypeReference ref;
+ if (cn.length == 1) {
+ ref = new SingleTypeReference(cn[0], 0);
+ } else {
+ ref = new QualifiedTypeReference(cn,new long[cn.length]);
+ }
+
+ TypeBinding guessedType = null;
+ switch (scope.kind) {
+ case Scope.COMPILATION_UNIT_SCOPE:
+ case Scope.METHOD_SCOPE :
+ case Scope.BLOCK_SCOPE :
+ guessedType = ref.resolveType((BlockScope)scope);
+ break;
+ case Scope.CLASS_SCOPE :
+ guessedType = ref.resolveType((ClassScope)scope);
+ break;
+ }
+
+
+ if (guessedType != null && guessedType.isValidBinding()) {
+ if (guessedType instanceof SourceTypeBinding) {
+ SourceTypeBinding refBinding = (SourceTypeBinding) guessedType;
+
+ if (refBinding.scope == null || refBinding.classScope.referenceContext == null) return null;
+
+ TypeDeclaration typeDeclaration = refBinding.classScope.referenceContext;
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+
+ next : for (int i = 0; i < methods.length; i++) {
+ AbstractMethodDeclaration method = methods[i];
+
+ if (!method.isConstructor()) continue next;
+
+ Argument[] arguments = method.arguments;
+ int argumentsLength = arguments == null ? 0 : arguments.length;
+
+ if (parameterCount != argumentsLength) continue next;
+
+ for (int j = 0; j < argumentsLength; j++) {
+ char[] argumentTypeName = getTypeName(arguments[j].type);
+
+ if (!CharOperation.equals(argumentTypeName, parameterTypes[j])) {
+ continue next;
+ }
+ }
+
+ refBinding.resolveTypesFor(method.binding); // force resolution
+ if (method.binding == null) continue next;
+ return getSignature(method.binding);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static char[] getTypeName(TypeReference typeReference) {
+ char[] typeName = CharOperation.concatWith(typeReference.getTypeName(), '.');
+ int dims = typeReference.dimensions();
+ if (dims > 0) {
+ int length = typeName.length;
+ int newLength = length + (dims*2);
+ System.arraycopy(typeName, 0, typeName = new char[newLength], 0, length);
+ for (int k = length; k < newLength; k += 2) {
+ typeName[k] = '[';
+ typeName[k+1] = ']';
+ }
+ }
+
+ return typeName;
+ }
+
+ /**
+ * Represents a constructor accepted from the index.
+ */
+ private static class AcceptedConstructor {
+ /**
+ * Modifiers to the constructor such as public/private
+ *
+ * @see Flags
+ */
+ public int modifiers;
+
+ /** Name of the type the constructor is for
*/
+ public char[] typeName;
+
+ /** Number of parameters for the constructor, or -1 for a default constructor
*/
+ public int parameterCount;
+
+ /** Type names of the parameters, should be same length as parameterCount
*/
+ public char[][] parameterTypes;
+
+ /** Names of the parameters, should be same length as parameterCount
*/
+ public char[][] parameterNames;
+
+ /**
+ * Accessibility of the constructor
+ *
+ * @see IAccessRule
+ */
+ public int accessibility;
+
+ /**
+ * Constructor
+ *
+ * @param modifiers Modifiers to the constructor such as public/private
+ * @param typeName Name of the type the constructor is for
+ * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor
+ * @param parameterTypes Type names of the parameters, should be same length as parameterCount
+ * @param parameterNames Names of the parameters, should be same length as parameterCount
+ * @param accessibility Accessibility of the constructor
+ *
+ * @see Flags
+ * @see IAccessRule
+ */
+ private AcceptedConstructor(
+ int modifiers,
+ char[] typeName,
+ int parameterCount,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ int accessibility) {
+
+ this.modifiers = modifiers;
+ this.typeName = typeName;
+ this.parameterCount = parameterCount;
+ this.parameterTypes = parameterTypes;
+ this.parameterNames = parameterNames;
+ this.accessibility = accessibility;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('{');
+ buffer.append(',');
+ buffer.append(this.typeName);
+ buffer.append('}');
+ return buffer.toString();
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java
new file mode 100644
index 0000000..d9a0c98
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISearchRequestor.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import org.eclipse.wst.jsdt.core.Flags;
+import org.eclipse.wst.jsdt.core.IAccessRule;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+
+/**
+ * This is the internal requestor passed to the searchable name environment
+ * so as to process the multiple search results as they are discovered.
+ *
+ * It is used to allow the code assist engine to add some more information
+ * to the raw name environment results before answering them to the UI.
+ */
+public interface ISearchRequestor {
+ /**
+ * One result of the search consists of a new type.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.I".
+ * The default package is represented by an empty array.
+ */
+ public void acceptType(char[] packageName, char [] fileName, char[] typeName, char[][] enclosingTypeNames, int modifiers, AccessRestriction accessRestriction);
+ public void acceptBinding(char[] packageName, char [] fileName, char[] bindingName, int bindingType, int modifiers, AccessRestriction accessRestriction);
+
+ /**
+ * One result of the search consists of a new package.
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+ public void acceptPackage(char[] packageName);
+
+ /**
+ * Accepts a constructor found during an index search.
+ *
+ * @param modifiers Modifiers to the constructor such as public/private
+ * @param typeName Name of the type the constructor is for
+ * @param parameterCount Number of parameters for the constructor, or -1 for a default constructor
+ * @param parameterTypes Type names of the parameters, should be same length as parameterCount
+ * @param parameterNames Names of the parameters, should be same length as parameterCount
+ * @param path to the document containing the constructor match
+ * @param access Accessibility of the constructor
+ *
+ * @see Flags
+ * @see IAccessRule
+ */
+ public void acceptConstructor(
+ int modifiers,
+ char[] typeName,
+ int parameterCount,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ String path,
+ AccessRestriction access);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISelectionRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISelectionRequestor.java
new file mode 100644
index 0000000..79b87aa
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ISelectionRequestor.java
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+
+/**
+ * A selection requestor accepts results from the selection engine.
+ */
+public interface ISelectionRequestor {
+ /**
+ * Code assist notification of a enum selection.
+ * @param packageName char[]
+ * Declaring package name of the type.
+ *
+ * @param annotationName char[]
+ * Name of the type.
+ *
+ * @param isDeclaration boolean
+ * Answer if the selected type is a declaration
+ *
+ * @param genericTypeSignature
+ * genric type signature of the selected type if it is a
+ * parameterized type
+ *
+ * @param start
+ * Start of the selection
+ *
+ * @param end
+ * End of the selection
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+ void acceptType(
+ char[] packageName,
+ char[] fileName,
+ char[] annotationName,
+ int modifiers,
+ boolean isDeclaration,
+ char[] genericTypeSignature,
+ int start,
+ int end);
+
+ /**
+ * Code assist notification of a compilation error detected during selection.
+ * @param error CategorizedProblem
+ * Only problems which are categorized as errors are notified to the requestor,
+ * warnings are silently ignored.
+ * In case an error got signaled, no other completions might be available,
+ * therefore the problem message should be presented to the user.
+ * The source positions of the problem are related to the source where it was
+ * detected (might be in another compilation unit, if it was indirectly requested
+ * during the code assist process).
+ * Note: the problem knows its originating file name.
+ */
+ void acceptError(CategorizedProblem error);
+
+ /**
+ * Code assist notification of a field selection.
+ * @param declaringTypePackageName char[]
+ * Name of the package in which the type that contains this field is declared.
+ *
+ * @param declaringTypeName char[]
+ * Name of the type declaring this new field.
+ *
+ * @param name char[]
+ * Name of the field.
+ *
+ * @param isDeclaration boolean
+ * Answer if the selected field is a declaration
+ *
+ * @param uniqueKey
+ * unique key of this field
+ *
+ * @param start
+ * Start of the selection
+ *
+ * @param end
+ * End of the selection
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+ void acceptField(
+ char[] declaringTypePackageName,
+ char[] fileName,
+ char[] declaringTypeName,
+ char[] name,
+ boolean isDeclaration,
+ char[] uniqueKey,
+ int start,
+ int end);
+
+ /**
+ * Code assist notification of a method selection.
+ * @param declaringTypePackageName char[]
+ * Name of the package in which the type that contains this new method is declared.
+ *
+ * @param declaringTypeName char[]
+ * Name of the type declaring this new method.
+ *
+ * @param enclosingDeclaringTypeSignature String
+ * Type signature of the declaring type of the declaring type or null
+ * if declaring type is a top level type.
+ *
+ * @param selector char[]
+ * Name of the new method.
+ *
+ * @param parameterPackageNames char[][]
+ * Names of the packages in which the parameter types are declared.
+ * Should contain as many elements as parameterTypeNames.
+ *
+ * @param parameterTypeNames char[][]
+ * Names of the parameters types.
+ * Should contain as many elements as parameterPackageNames.
+ *
+ * @param parameterSignatures String[]
+ * Signature of the parameters types.
+ * Should contain as many elements as parameterPackageNames.
+ *
+ * @param isConstructor boolean
+ * Answer if the method is a constructor.
+ *
+ * @param isDeclaration boolean
+ * Answer if the selected method is a declaration
+ *
+ * @param uniqueKey
+ * unique key of the method
+ *
+ * @param start
+ * Start of the selection
+ *
+ * @param end
+ * End of the selection
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Base types are in the form "int" or "boolean".
+ * Array types are in the qualified form "M[]" or "int[]".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+ // parameters 'isDeclaration', 'start' and 'end' are use to distinguish duplicate methods declarations
+ void acceptMethod(
+ char[] declaringTypePackageName,
+ char[] fileName,
+ char[] declaringTypeName,
+ String enclosingDeclaringTypeSignature,
+ char[] selector,
+ char[][] parameterPackageNames,
+ char[][] parameterTypeNames,
+ String[] parameterSignatures,
+ char[][] typeParameterNames,
+ char[][][] typeParameterBoundNames,
+ boolean isConstructor,
+ boolean isDeclaration,
+ char[] uniqueKey,
+ int start,
+ int end);
+
+ /**
+ * Code assist notification of a package selection.
+ * @param packageName char[]
+ * The package name.
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+ void acceptPackage(char[] packageName);
+ /**
+ * Code assist notification of a type parameter selection.
+ *
+ * @param declaringTypePackageName char[]
+ * Name of the package in which the type that contains this new method is declared.
+ *
+ * @param declaringTypeName char[]
+ * Name of the type declaring this new method.
+ *
+ * @param typeParameterName char[]
+ * Name of the type parameter.
+ *
+ * @param isDeclaration boolean
+ * Answer if the selected type parameter is a declaration
+ *
+ * @param start
+ * Start of the selection
+ *
+ * @param end
+ * End of the selection
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+ void acceptTypeParameter(
+ char[] declaringTypePackageName,
+ char[] fileName,
+ char[] declaringTypeName,
+ char[] typeParameterName,
+ boolean isDeclaration,
+ int start,
+ int end);
+
+ /**
+ * Code assist notification of a type parameter selection.
+ *
+ * @param declaringTypePackageName char[]
+ * Name of the package in which the type that contains this new method is declared.
+ *
+ * @param declaringTypeName char[]
+ * Name of the type declaring this new method.
+ *
+ * @param selector char[]
+ * Name of the declaring method.
+ *
+ * @param selectorStart int
+ * Start of the selector.
+ *
+ * @param selectorEnd int
+ * End of the selector.
+ *
+ * @param typeParameterName char[]
+ * Name of the type parameter.
+ *
+ * @param isDeclaration boolean
+ * Answer if the selected type parameter is a declaration
+ *
+ * @param start
+ * Start of the selection
+ *
+ * @param end
+ * End of the selection
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * Nested type names are in the qualified form "A.M".
+ * The default package is represented by an empty array.
+ */
+ void acceptMethodTypeParameter(
+ char[] declaringTypePackageName,
+ char[] fileName,
+ char[] declaringTypeName,
+ char[] selector,
+ int selectorStart,
+ int selectorEnd,
+ char[] typeParameterName,
+ boolean isDeclaration,
+ int start,
+ int end);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/InternalCompletionContext.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/InternalCompletionContext.java
new file mode 100644
index 0000000..9f5a572
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/InternalCompletionContext.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+
+/**
+ * Internal completion context
+ * @since 3.1
+ */
+public class InternalCompletionContext {
+ protected char[][] expectedTypesSignatures;
+ protected char[][] expectedTypesKeys;
+ protected int javadoc;
+
+ protected int offset = -1;
+ protected int tokenStart = -1;
+ protected int tokenEnd = -1;
+ protected char[] token = null;
+ protected int tokenKind;
+
+ protected void setExpectedTypesSignatures(char[][] expectedTypesSignatures) {
+ this.expectedTypesSignatures = expectedTypesSignatures;
+ }
+
+ protected void setExpectedTypesKeys(char[][] expectedTypesKeys) {
+ this.expectedTypesKeys = expectedTypesKeys;
+ }
+
+ protected void setJavadoc(int javadoc) {
+ this.javadoc = javadoc;
+ }
+
+ protected void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+ protected void setTokenRange(int start, int end) {
+ this.setTokenRange(start, end, -1);
+ }
+ protected void setTokenRange(int start, int end, int endOfEmptyToken) {
+ this.tokenStart = start;
+ this.tokenEnd = endOfEmptyToken > end ? endOfEmptyToken : end;
+
+ // Work around for bug 132558 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=132558).
+ // completionLocation can be -1 if the completion occur at the start of a file or
+ // the start of a code snippet but this API isn't design to support negative position.
+ if(this.tokenEnd == -1) {
+ this.tokenEnd = 0;
+ }
+ }
+
+ protected void setToken(char[] token) {
+ this.token = token;
+ }
+
+ protected void setTokenKind(int tokenKind) {
+ this.tokenKind = tokenKind;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/InternalCompletionProposal.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/InternalCompletionProposal.java
new file mode 100644
index 0000000..35e732b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/InternalCompletionProposal.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import org.eclipse.wst.jsdt.core.IAccessRule;
+import org.eclipse.wst.jsdt.core.IJavaScriptProject;
+import org.eclipse.wst.jsdt.core.IFunction;
+import org.eclipse.wst.jsdt.core.IType;
+import org.eclipse.wst.jsdt.core.JavaScriptModelException;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.core.BinaryType;
+import org.eclipse.wst.jsdt.internal.core.NameLookup;
+
+/**
+ * Internal completion proposal
+ * @since 3.1
+ */
+public class InternalCompletionProposal {
+ private static Object NO_ATTACHED_SOURCE = new Object();
+
+ static final char[] ARG = "arg".toCharArray(); //$NON-NLS-1$
+ static final char[] ARG0 = "arg0".toCharArray(); //$NON-NLS-1$
+ static final char[] ARG1 = "arg1".toCharArray(); //$NON-NLS-1$
+ static final char[] ARG2 = "arg2".toCharArray(); //$NON-NLS-1$
+ static final char[] ARG3 = "arg3".toCharArray(); //$NON-NLS-1$
+ static final char[][] ARGS1 = new char[][]{ARG0};
+ static final char[][] ARGS2 = new char[][]{ARG0, ARG1};
+ static final char[][] ARGS3 = new char[][]{ARG0, ARG1, ARG2};
+ static final char[][] ARGS4 = new char[][]{ARG0, ARG1, ARG2, ARG3};
+
+ protected CompletionEngine completionEngine;
+ protected NameLookup nameLookup;
+
+ protected char[] declarationPackageName;
+ protected char[] declarationTypeName;
+ protected char[] packageName;
+ protected char[] typeName;
+ protected char[][] parameterPackageNames;
+ protected char[][] parameterTypeNames;
+
+ protected char[] originalSignature;
+
+ protected int accessibility = IAccessRule.K_ACCESSIBLE;
+
+ protected boolean isConstructor = false;
+
+ protected char[][] createDefaultParameterNames(int length) {
+ char[][] parameterNames;
+ switch (length) {
+ case 0 :
+ parameterNames = new char[length][];
+ break;
+ case 1 :
+ parameterNames = ARGS1;
+ break;
+ case 2 :
+ parameterNames = ARGS2;
+ break;
+ case 3 :
+ parameterNames = ARGS3;
+ break;
+ case 4 :
+ parameterNames = ARGS4;
+ break;
+ default :
+ parameterNames = new char[length][];
+ for (int i = 0; i < length; i++) {
+ parameterNames[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
+ }
+ break;
+ }
+ return parameterNames;
+ }
+ protected char[][] findMethodParameterNames(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] paramTypeNames){
+ if(paramTypeNames == null || declaringTypeName == null) return null;
+
+ char[][] parameterNames = null;
+ int length = paramTypeNames.length;
+
+ char[] tName = CharOperation.concat(declaringTypePackageName,declaringTypeName,'.');
+ Object cachedType = this.completionEngine.typeCache.get(tName);
+
+ IType type = null;
+ if(cachedType != null) {
+ if(cachedType != NO_ATTACHED_SOURCE && cachedType instanceof BinaryType) {
+ type = (BinaryType)cachedType;
+ }
+ } else {
+ // TODO (david) shouldn't it be NameLookup.ACCEPT_ALL ?
+ NameLookup.Answer answer = this.nameLookup.findType(new String(tName),
+ false,
+ NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES,
+ true/* consider secondary types */,
+ false/* do NOT wait for indexes */,
+ false/*don't check restrictions*/,
+ null);
+ type = answer == null ? null : answer.type;
+ if(type instanceof BinaryType){
+ this.completionEngine.typeCache.put(tName, type);
+ } else {
+ type = null;
+ }
+ }
+
+ if(type != null) {
+ String[] args = new String[length];
+ for(int i = 0; i< length ; i++){
+ args[i] = new String(paramTypeNames[i]);
+ }
+ IFunction method = type.getFunction(new String(selector),args);
+ try{
+ parameterNames = new char[length][];
+ String[] params = method.getParameterNames();
+ for(int i = 0; i< length ; i++){
+ parameterNames[i] = params[i].toCharArray();
+ }
+ } catch(JavaScriptModelException e){
+ parameterNames = null;
+ }
+ }
+
+ // default parameters name
+ if(parameterNames == null) {
+ parameterNames = createDefaultParameterNames(length);
+ }
+
+ return parameterNames;
+ }
+
+ protected char[] getDeclarationPackageName() {
+ return this.declarationPackageName;
+ }
+
+ protected char[] getDeclarationTypeName() {
+ return this.declarationTypeName;
+ }
+
+ protected char[] getPackageName() {
+ return this.packageName;
+ }
+
+ protected char[] getTypeName() {
+ return this.typeName;
+ }
+
+ protected char[][] getParameterPackageNames() {
+ return this.parameterPackageNames;
+ }
+
+
+ protected char[][] getParameterTypeNames() {
+ return this.parameterTypeNames;
+ }
+
+ protected void setDeclarationPackageName(char[] declarationPackageName) {
+ this.declarationPackageName = declarationPackageName;
+ }
+
+ protected void setDeclarationTypeName(char[] declarationTypeName) {
+ this.declarationTypeName = declarationTypeName;
+ }
+
+ protected void setPackageName(char[] packageName) {
+ this.packageName = packageName;
+ }
+
+ protected void setTypeName(char[] typeName) {
+ this.typeName = typeName;
+ }
+
+ protected void setParameterPackageNames(char[][] parameterPackageNames) {
+ this.parameterPackageNames = parameterPackageNames;
+ }
+
+ protected void setParameterTypeNames(char[][] parameterTypeNames) {
+ this.parameterTypeNames = parameterTypeNames;
+ }
+
+ protected void setAccessibility(int kind) {
+ this.accessibility = kind;
+ }
+
+ protected void setIsContructor(boolean isConstructor) {
+ this.isConstructor = isConstructor;
+ }
+ public void setOriginalSignature(char[] originalSignature) {
+ this.originalSignature = originalSignature;
+ }
+
+ public IJavaScriptProject getJavaProject() {
+ return completionEngine.javaProject;
+ }
+
+ public NameLookup getNameLookup() {
+ return nameLookup;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java
new file mode 100644
index 0000000..b38679c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/MissingTypesGuesser.java
@@ -0,0 +1,440 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+
+public class MissingTypesGuesser extends ASTVisitor {
+ public static interface GuessedTypeRequestor {
+ public void accept(
+ TypeBinding guessedType,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds,
+ boolean hasProblems);
+
+ }
+
+ private static class ResolutionCleaner extends ASTVisitor {
+ private HashtableOfObjectToInt bitsMap = new HashtableOfObjectToInt();
+ private boolean firstCall = true;
+
+ public ResolutionCleaner(){
+ super();
+ }
+
+ private void cleanUp(TypeReference typeReference) {
+ if (this.firstCall) {
+ this.bitsMap.put(typeReference, typeReference.bits);
+ } else {
+ typeReference.bits = this.bitsMap.get(typeReference);
+ }
+ typeReference.resolvedType = null;
+ }
+
+ public void cleanUp(TypeReference convertedType, BlockScope scope) {
+ convertedType.traverse(this, scope);
+ this.firstCall = false;
+ }
+
+ public void cleanUp(TypeReference convertedType, ClassScope scope) {
+ convertedType.traverse(this, scope);
+ this.firstCall = false;
+ }
+
+ public boolean visit(SingleTypeReference singleTypeReference, BlockScope scope) {
+ this.cleanUp(singleTypeReference);
+ return true;
+ }
+
+ public boolean visit(SingleTypeReference singleTypeReference, ClassScope scope) {
+ this.cleanUp(singleTypeReference);
+ return true;
+ }
+
+ public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ this.cleanUp(arrayTypeReference);
+ return true;
+ }
+
+ public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ this.cleanUp(arrayTypeReference);
+ return true;
+ }
+
+ public boolean visit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope) {
+ this.cleanUp(qualifiedTypeReference);
+ return true;
+ }
+
+ public boolean visit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope) {
+ this.cleanUp(qualifiedTypeReference);
+ return true;
+ }
+
+ public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope) {
+ this.cleanUp(arrayQualifiedTypeReference);
+ return true;
+ }
+
+ public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope) {
+ this.cleanUp(arrayQualifiedTypeReference);
+ return true;
+ }
+ }
+
+ private CompletionEngine.CompletionProblemFactory problemFactory ;
+ private SearchableEnvironment nameEnvironment;
+
+ private HashMap substituedTypes;
+ private HashMap originalTypes;
+ private int combinationsCount;
+
+ public MissingTypesGuesser(CompletionEngine completionEngine) {
+ this.problemFactory = completionEngine.problemFactory;
+ this.nameEnvironment = completionEngine.nameEnvironment;
+ }
+
+ private boolean computeMissingElements(
+ QualifiedTypeReference[] substituedTypeNodes,
+ char[][][] originalTypeNames,
+ Binding[] missingElements,
+ int[] missingElementsStarts,
+ int[] missingElementsEnds) {
+ int length = substituedTypeNodes.length;
+
+ for (int i = 0; i < length; i++) {
+ TypeReference substituedType = substituedTypeNodes[i];
+ if (substituedType.resolvedType == null) return false;
+ ReferenceBinding erasure = (ReferenceBinding)substituedType.resolvedType.leafComponentType();
+ Binding missingElement;
+ int depthToRemove = originalTypeNames[i].length - 1 ;
+ if (depthToRemove == 0) {
+ missingElement = erasure;
+ } else {
+ int depth = erasure.depth() + 1;
+
+ if (depth > depthToRemove) {
+ missingElement = erasure.enclosingTypeAt(depthToRemove);
+ } else {
+ return false;
+ ///////////////////////////////////////////////////////////
+ //// Uncomment the following code to return missing package
+ ///////////////////////////////////////////////////////////
+ //depthToRemove -= depth;
+ //PackageBinding packageBinding = erasure.getPackage();
+ //while(depthToRemove > 0) {
+ // packageBinding = packageBinding.parent;
+ // depthToRemove--;
+ //}
+ //missingElement = packageBinding;
+ }
+ }
+
+ missingElements[i] = missingElement;
+ missingElementsStarts[i] = substituedType.sourceStart;
+ missingElementsEnds[i] = substituedType.sourceEnd + 1;
+
+ }
+
+ return true;
+ }
+
+ private TypeReference convert(ArrayQualifiedTypeReference typeRef) {
+ if (typeRef.resolvedType != null) {
+ if (typeRef.resolvedType.isValidBinding()) {
+ ArrayQualifiedTypeReference convertedType =
+ new ArrayQualifiedTypeReference(
+ typeRef.tokens,
+ typeRef.dimensions(),
+ typeRef.sourcePositions);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = typeRef.sourceEnd;
+ return convertedType;
+ } else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
+ // only the first token must be resolved
+ if(((ReferenceBinding)typeRef.resolvedType.leafComponentType()).compoundName.length != 1) return null;
+
+ char[][] typeName = typeRef.getTypeName();
+ char[][][] typeNames = findTypeNames(typeName);
+ if(typeNames == null || typeNames.length == 0) return null;
+ ArrayQualifiedTypeReference convertedType =
+ new ArrayQualifiedTypeReference(
+ typeNames[0],
+ typeRef.dimensions(),
+ new long[typeNames[0].length]);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = (int)(typeRef.sourcePositions[0] & 0x00000000FFFFFFFFL);
+ this.substituedTypes.put(convertedType, typeNames);
+ this.originalTypes.put(convertedType, typeName);
+ this.combinationsCount *= typeNames.length;
+ return convertedType;
+ }
+ }
+ return null;
+ }
+
+ private TypeReference convert(ArrayTypeReference typeRef) {
+ if (typeRef.resolvedType != null) {
+ if (typeRef.resolvedType.isValidBinding()) {
+ ArrayTypeReference convertedType =
+ new ArrayTypeReference(
+ typeRef.token,
+ typeRef.dimensions,
+ 0);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = typeRef.originalSourceEnd;
+ return convertedType;
+ } else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
+ char[][] typeName = typeRef.getTypeName();
+ char[][][] typeNames = findTypeNames(typeName);
+ if(typeNames == null || typeNames.length == 0) return null;
+ ArrayQualifiedTypeReference convertedType =
+ new ArrayQualifiedTypeReference(
+ typeNames[0],
+ typeRef.dimensions,
+ new long[typeNames[0].length]);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = typeRef.originalSourceEnd;
+ this.substituedTypes.put(convertedType, typeNames);
+ this.originalTypes.put(convertedType, typeName);
+ this.combinationsCount *= typeNames.length;
+ return convertedType;
+ }
+ }
+ return null;
+ }
+
+ private TypeReference convert(QualifiedTypeReference typeRef) {
+ if (typeRef.resolvedType != null) {
+ if (typeRef.resolvedType.isValidBinding()) {
+ QualifiedTypeReference convertedType = new QualifiedTypeReference(typeRef.tokens, typeRef.sourcePositions);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = typeRef.sourceEnd;
+ return convertedType;
+ } else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
+ // only the first token must be resolved
+ if(((ReferenceBinding)typeRef.resolvedType).compoundName.length != 1) return null;
+
+ char[][] typeName = typeRef.getTypeName();
+ char[][][] typeNames = findTypeNames(typeName);
+ if(typeNames == null || typeNames.length == 0) return null;
+ QualifiedTypeReference convertedType = new QualifiedTypeReference(typeNames[0], new long[typeNames[0].length]);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = (int)(typeRef.sourcePositions[0] & 0x00000000FFFFFFFFL);
+ this.substituedTypes.put(convertedType, typeNames);
+ this.originalTypes.put(convertedType, typeName);
+ this.combinationsCount *= typeNames.length;
+ return convertedType;
+ }
+ }
+ return null;
+ }
+
+ private TypeReference convert(SingleTypeReference typeRef) {
+ if (typeRef.resolvedType != null) {
+ if (typeRef.resolvedType.isValidBinding()) {
+ SingleTypeReference convertedType = new SingleTypeReference(typeRef.token, 0);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = typeRef.sourceEnd;
+ return convertedType;
+ } else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
+ char[][] typeName = typeRef.getTypeName();
+ char[][][] typeNames = findTypeNames(typeName);
+ if(typeNames == null || typeNames.length == 0) return null;
+ QualifiedTypeReference convertedType = new QualifiedTypeReference(typeNames[0], new long[typeNames[0].length]);
+ convertedType.sourceStart = typeRef.sourceStart;
+ convertedType.sourceEnd = typeRef.sourceEnd;
+ this.substituedTypes.put(convertedType, typeNames);
+ this.originalTypes.put(convertedType, typeName);
+ this.combinationsCount *= typeNames.length;
+ return convertedType;
+ }
+ }
+ return null;
+ }
+
+ private TypeReference convert(TypeReference typeRef) {
+ if (typeRef instanceof ArrayTypeReference) {
+ return convert((ArrayTypeReference)typeRef);
+ } else if(typeRef instanceof ArrayQualifiedTypeReference) {
+ return convert((ArrayQualifiedTypeReference)typeRef);
+ } else if (typeRef instanceof SingleTypeReference) {
+ return convert((SingleTypeReference)typeRef);
+ } else if (typeRef instanceof QualifiedTypeReference) {
+ return convert((QualifiedTypeReference)typeRef);
+ }
+ return null;
+ }
+
+ private char[][][] findTypeNames(char[][] missingTypeName) {
+ char[] missingSimpleName = missingTypeName[missingTypeName.length - 1];
+ final boolean isQualified = missingTypeName.length > 1;
+ final char[] missingFullyQualifiedName =
+ isQualified ? CharOperation.concatWith(missingTypeName, '.') : null;
+ final ArrayList results = new ArrayList();
+ ISearchRequestor storage = new ISearchRequestor() {
+
+ public void acceptPackage(char[] packageName) {
+ // package aren't searched
+ }
+ public void acceptType(
+ char[] packageName,
+ char[] fileName,
+ char[] typeName,
+ char[][] enclosingTypeNames,
+ int modifiers,
+ AccessRestriction accessRestriction) {
+ char[] fullyQualifiedName = CharOperation.concat(packageName, CharOperation.concat(CharOperation.concatWith(enclosingTypeNames, '.'), typeName, '.'), '.');
+ if (isQualified && !CharOperation.endsWith(fullyQualifiedName, missingFullyQualifiedName)) return;
+ char[][] compoundName = CharOperation.splitOn('.', fullyQualifiedName);
+ results.add(compoundName);
+ }
+ public void acceptBinding(char[] packageName, char[] fileName, char[] bindingName, int bindingType, int modifiers, AccessRestriction accessRestriction) {
+ //do nothing
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor(
+ * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void acceptConstructor(int modifiers, char[] typeName,
+ int parameterCount, char[][] parameterTypes, char[][] parameterNames,
+ String path, AccessRestriction access) {
+
+ //do nothing
+ }
+
+ };
+ nameEnvironment.findExactTypes(missingSimpleName, true, IJavaScriptSearchConstants.TYPE, storage);
+ if(results.size() == 0) return null;
+ return (char[][][])results.toArray(new char[results.size()][0][0]);
+ }
+
+ private char[][] getOriginal(TypeReference typeRef) {
+ return (char[][])this.originalTypes.get(typeRef);
+ }
+
+ private QualifiedTypeReference[] getSubstituedTypes() {
+ Set types = this.substituedTypes.keySet();
+ return (QualifiedTypeReference[]) types.toArray(new QualifiedTypeReference[types.size()]);
+ }
+
+ private char[][][] getSubstitution(TypeReference typeRef) {
+ return (char[][][])this.substituedTypes.get(typeRef);
+ }
+
+ public void guess(TypeReference typeRef, Scope scope, GuessedTypeRequestor requestor) {
+ this.substituedTypes = new HashMap();
+ this.originalTypes = new HashMap();
+ this.combinationsCount = 1;
+
+ TypeReference convertedType = convert(typeRef);
+
+ if(convertedType == null) return;
+
+ QualifiedTypeReference[] substituedTypeNodes = this.getSubstituedTypes();
+ int length = substituedTypeNodes.length;
+
+ int[] substitutionsIndexes = new int[substituedTypeNodes.length];
+ char[][][][] subtitutions = new char[substituedTypeNodes.length][][][];
+ char[][][] originalTypeNames = new char[substituedTypeNodes.length][][];
+ for (int i = 0; i < substituedTypeNodes.length; i++) {
+ subtitutions[i] = this.getSubstitution(substituedTypeNodes[i]);
+ originalTypeNames[i] = this.getOriginal(substituedTypeNodes[i]);
+ }
+
+ ResolutionCleaner resolutionCleaner = new ResolutionCleaner();
+ for (int i = 0; i < this.combinationsCount; i++) {
+
+ nextSubstitution(substituedTypeNodes, subtitutions, substitutionsIndexes);
+
+
+ this.problemFactory.startCheckingProblems();
+ TypeBinding guessedType = null;
+ switch (scope.kind) {
+ case Scope.METHOD_SCOPE :
+ case Scope.BLOCK_SCOPE :
+ resolutionCleaner.cleanUp(convertedType, (BlockScope)scope);
+ guessedType = convertedType.resolveType((BlockScope)scope);
+ break;
+ case Scope.CLASS_SCOPE :
+ resolutionCleaner.cleanUp(convertedType, (ClassScope)scope);
+ guessedType = convertedType.resolveType((ClassScope)scope);
+ break;
+ }
+ this.problemFactory.stopCheckingProblems();
+ if (!this.problemFactory.hasForbiddenProblems) {
+ if (guessedType != null) {
+ Binding[] missingElements = new Binding[length];
+ int[] missingElementsStarts = new int[length];
+ int[] missingElementsEnds = new int[length];
+
+ if(computeMissingElements(
+ substituedTypeNodes,
+ originalTypeNames,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds)) {
+ requestor.accept(
+ guessedType,
+ missingElements,
+ missingElementsStarts,
+ missingElementsEnds,
+ this.problemFactory.hasAllowedProblems);
+ }
+ }
+ }
+ }
+ }
+ private void nextSubstitution(
+ QualifiedTypeReference[] substituedTypeNodes,
+ char[][][][] subtitutions,
+ int[] substitutionsIndexes) {
+ int length = substituedTypeNodes.length;
+
+ done : for (int i = 0; i < length; i++) {
+ if(substitutionsIndexes[i] < subtitutions[i].length - 1) {
+ substitutionsIndexes[i]++;
+ break done;
+ } else {
+ substitutionsIndexes[i] = 0;
+ }
+ }
+
+ for (int i = 0; i < length; i++) {
+ QualifiedTypeReference qualifiedTypeReference = substituedTypeNodes[i];
+ qualifiedTypeReference.tokens = subtitutions[i][substitutionsIndexes[i]];
+ qualifiedTypeReference.sourcePositions = new long[qualifiedTypeReference.tokens.length];
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/RelevanceConstants.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/RelevanceConstants.java
new file mode 100644
index 0000000..ce267f1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/RelevanceConstants.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+public interface RelevanceConstants {
+
+ int R_DEFAULT = 0;
+ int R_INTERESTING = 5;
+ int R_CASE = 10;
+ int R_CAMEL_CASE = 5;
+ int R_EXACT_NAME = 4;
+ int R_EXPECTED_TYPE = 20;
+ int R_EXACT_EXPECTED_TYPE = 30;
+ int R_CLASS = 20;
+ int R_EXCEPTION = 20;
+ int R_ABSTRACT_METHOD = 20;
+ int R_NON_STATIC = 11;
+ int R_UNQUALIFIED = 3;
+ int R_QUALIFIED = 2;
+ int R_NAME_FIRST_PREFIX = 6;
+ int R_NAME_PREFIX = 5;
+ int R_NAME_FIRST_SUFFIX = 4;
+ int R_NAME_SUFFIX = 3;
+ int R_NAME_LESS_NEW_CHARACTERS = 15;
+ int R_METHOD_OVERIDE = 3;
+ int R_NON_RESTRICTED = 3;
+ int R_TRUE_OR_FALSE = 1;
+ int R_INLINE_TAG = 31;
+ int R_VALUE_TAG = 31;
+ int R_NON_INHERITED = 2;
+ int R_NO_PROBLEMS = 1;
+ int R_RESOLVED = 1;
+ int R_TARGET = 5;
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java
new file mode 100644
index 0000000..0b7164b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/SelectionEngine.java
@@ -0,0 +1,1301 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.Signature;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.Engine;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionNodeFound;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnImportReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnPackageReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionOnSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.codeassist.select.SelectionParser;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalFunctionBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MemberTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.parser.SourceTypeConverter;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+import org.eclipse.wst.jsdt.internal.core.SelectionRequestor;
+import org.eclipse.wst.jsdt.internal.core.SourceType;
+import org.eclipse.wst.jsdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.wst.jsdt.internal.core.util.ASTNodeFinder;
+
+/**
+ * The selection engine is intended to infer the nature of a selected name in some
+ * source code. This name can be qualified.
+ *
+ * Selection is resolving context using a name environment (no need to search), assuming
+ * the source where selection occurred is correct and will not perform any completion
+ * attempt. If this was the desired behavior, a call to the CompletionEngine should be
+ * performed instead.
+ */
+public final class SelectionEngine extends Engine implements ISearchRequestor {
+
+ public static boolean DEBUG = false;
+ public static boolean PERF = false;
+
+ SelectionParser parser;
+ ISelectionRequestor requestor;
+
+ boolean acceptedAnswer;
+
+ private int actualSelectionStart;
+ private int actualSelectionEnd;
+ private char[] selectedIdentifier;
+
+ private char[][][] acceptedClasses;
+ private int[] acceptedClassesModifiers;
+ private char[][][] acceptedInterfaces;
+ private int[] acceptedInterfacesModifiers;
+ private char[][][] acceptedEnums;
+ private int[] acceptedEnumsModifiers;
+ private char[][][] acceptedAnnotations;
+ private int[] acceptedAnnotationsModifiers;
+ int acceptedClassesCount;
+ int acceptedInterfacesCount;
+ int acceptedEnumsCount;
+ int acceptedAnnotationsCount;
+
+ boolean noProposal = true;
+ CategorizedProblem problem = null;
+
+ /**
+ * The SelectionEngine is responsible for computing the selected object.
+ *
+ * It requires a searchable name environment, which supports some
+ * specific search APIs, and a requestor to feed back the results to a UI.
+ *
+ * @param nameEnvironment org.eclipse.wst.jsdt.internal.core.SearchableEnvironment
+ * used to resolve type/package references and search for types/packages
+ * based on partial names.
+ *
+ * @param requestor org.eclipse.wst.jsdt.internal.codeassist.ISelectionRequestor
+ * since the engine might produce answers of various forms, the engine
+ * is associated with a requestor able to accept all possible completions.
+ *
+ * @param settings java.util.Map
+ * set of options used to configure the code assist engine.
+ */
+ public SelectionEngine(
+ SearchableEnvironment nameEnvironment,
+ ISelectionRequestor requestor,
+ Map settings) {
+
+ super(settings);
+
+ this.requestor = requestor;
+ this.nameEnvironment = nameEnvironment;
+
+ ProblemReporter problemReporter =
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+ this.compilerOptions,
+ new DefaultProblemFactory(Locale.getDefault())) {
+
+ public CategorizedProblem createProblem(
+ char[] fileName,
+ int problemId,
+ String[] problemArguments,
+ String[] messageArguments,
+ int severity,
+ int problemStartPosition,
+ int problemEndPosition,
+ int lineNumber,
+ int columnNumber) {
+ CategorizedProblem pb = super.createProblem(
+ fileName,
+ problemId,
+ problemArguments,
+ messageArguments,
+ severity,
+ problemStartPosition,
+ problemEndPosition,
+ lineNumber,
+ columnNumber);
+ if(SelectionEngine.this.problem == null && pb.isError() && (pb.getID() & IProblem.Syntax) == 0) {
+ SelectionEngine.this.problem = pb;
+ }
+
+ return pb;
+ }
+ };
+ this.lookupEnvironment =
+ new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+ this.parser = new SelectionParser(problemReporter);
+ }
+
+ public void acceptType(char[] packageName, char [] fileName, char[] simpleTypeName, char[][] enclosingTypeNames, int modifiers, AccessRestriction accessRestriction) {
+ char[] typeName = enclosingTypeNames == null ?
+ simpleTypeName :
+ CharOperation.concat(
+ CharOperation.concatWith(enclosingTypeNames, '.'),
+ simpleTypeName,
+ '.');
+
+ if (CharOperation.equals(simpleTypeName, this.selectedIdentifier)) {
+ char[] flatEnclosingTypeNames =
+ enclosingTypeNames == null || enclosingTypeNames.length == 0 ?
+ null :
+ CharOperation.concatWith(enclosingTypeNames, '.');
+ if(mustQualifyType(packageName, simpleTypeName, flatEnclosingTypeNames, modifiers)) {
+ int length = 0;
+ int kind = 0;
+ switch (kind) {
+ default:
+ char[][] acceptedClass = new char[3][];
+ acceptedClass[0] = packageName;
+ acceptedClass[1] = typeName;
+ acceptedClass[2] = fileName;
+
+ if(this.acceptedClasses == null) {
+ this.acceptedClasses = new char[10][][];
+ this.acceptedClassesModifiers = new int[10];
+ this.acceptedClassesCount = 0;
+ }
+ length = this.acceptedClasses.length;
+ if(length == this.acceptedClassesCount) {
+ int newLength = (length + 1)* 2;
+ System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[newLength][][], 0, length);
+ System.arraycopy(this.acceptedClassesModifiers, 0, this.acceptedClassesModifiers = new int[newLength], 0, length);
+ }
+ this.acceptedClassesModifiers[this.acceptedClassesCount] = modifiers;
+ this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass;
+ break;
+ }
+ } else {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ packageName,
+ fileName,
+ typeName,
+ modifiers,
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ this.acceptedAnswer = true;
+ }
+ }
+ }
+
+ public void acceptBinding(char[] packageName, char [] filename, char[] simpleTypeName, int bindingType, int modifiers, AccessRestriction accessRestriction) {
+ char[] typeName = simpleTypeName ;
+
+ if (CharOperation.equals(simpleTypeName, this.selectedIdentifier)) {
+ char[] flatEnclosingTypeNames = null;
+ if(mustQualifyType(packageName, simpleTypeName, flatEnclosingTypeNames, modifiers)) {
+ int length = 0;
+ int kind = 0;
+ switch (kind) {
+ default:
+ char[][] acceptedClass = new char[2][];
+ acceptedClass[0] = packageName;
+ acceptedClass[1] = typeName;
+
+ if(this.acceptedClasses == null) {
+ this.acceptedClasses = new char[10][][];
+ this.acceptedClassesModifiers = new int[10];
+ this.acceptedClassesCount = 0;
+ }
+ length = this.acceptedClasses.length;
+ if(length == this.acceptedClassesCount) {
+ int newLength = (length + 1)* 2;
+ System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[newLength][][], 0, length);
+ System.arraycopy(this.acceptedClassesModifiers, 0, this.acceptedClassesModifiers = new int[newLength], 0, length);
+ }
+ this.acceptedClassesModifiers[this.acceptedClassesCount] = modifiers;
+ this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass;
+ break;
+ }
+ } else {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ packageName,
+ filename,
+ typeName,
+ modifiers,
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ this.acceptedAnswer = true;
+ }
+ }
+ }
+
+ /**
+ * One result of the search consists of a new package.
+ * @param packageName char[]
+ *
+ * NOTE - All package names are presented in their readable form:
+ * Package names are in the form "a.b.c".
+ * The default package is represented by an empty array.
+ */
+ public void acceptPackage(char[] packageName) {
+ // implementation of interface method
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.ISearchRequestor#acceptConstructor(
+ * int, char[], int, char[][], char[][], java.lang.String, org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction)
+ */
+ public void acceptConstructor(int modifiers, char[] typeName,
+ int parameterCount, char[][] parameterTypes,
+ char[][] parameterNames, String path,
+ AccessRestriction access) {
+
+ // do nothing
+ }
+
+ private void acceptQualifiedTypes() {
+ if(this.acceptedClasses != null){
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedClassesCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedClasses[i][0],
+ this.acceptedClasses[i][2],
+ this.acceptedClasses[i][1],
+ this.acceptedClassesModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedClasses = null;
+ this.acceptedClassesModifiers = null;
+ this.acceptedClassesCount = 0;
+ }
+ if(this.acceptedInterfaces != null){
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedInterfacesCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedInterfaces[i][0],
+ null,
+ this.acceptedInterfaces[i][1],
+ this.acceptedInterfacesModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedInterfaces = null;
+ this.acceptedInterfacesModifiers = null;
+ this.acceptedInterfacesCount = 0;
+ }
+ if(this.acceptedAnnotations != null){
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedAnnotationsCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedAnnotations[i][0],
+ null,
+ this.acceptedAnnotations[i][1],
+ this.acceptedAnnotationsModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedAnnotations = null;
+ this.acceptedAnnotationsModifiers = null;
+ this.acceptedAnnotationsCount = 0;
+ }
+ if(this.acceptedEnums != null){
+ this.acceptedAnswer = true;
+ for (int i = 0; i < this.acceptedEnumsCount; i++) {
+ this.noProposal = false;
+ this.requestor.acceptType(
+ this.acceptedEnums[i][0],
+ null,
+ this.acceptedEnums[i][1],
+ this.acceptedEnumsModifiers[i],
+ false,
+ null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedEnums = null;
+ this.acceptedEnumsModifiers = null;
+ this.acceptedEnumsCount = 0;
+ }
+ }
+ private boolean checkSelection(
+ char[] source,
+ int selectionStart,
+ int selectionEnd) {
+
+ Scanner scanner = new Scanner();
+ scanner.setSource(source);
+
+ int lastIdentifierStart = -1;
+ int lastIdentifierEnd = -1;
+ char[] lastIdentifier = null;
+ int token;
+
+ if(selectionStart > selectionEnd){
+
+ // compute end position of the selection
+ int end = selectionEnd + 1 == source.length ? selectionEnd : selectionEnd + 1;
+ // compute start position of current line
+ int currentPosition = selectionStart - 1;
+ int nextCharacterPosition = selectionStart;
+ char currentCharacter = ' ';
+ boolean brokeLoop=false;
+ try {
+ lineLoop: while(currentPosition > 0){
+
+ if(source[currentPosition] == '\\' && source[currentPosition+1] == 'u') {
+ int pos = currentPosition + 2;
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ while (source[pos] == 'u') {
+ pos++;
+ }
+ int endOfUnicode = pos + 3;
+ if (end < endOfUnicode) {
+ if (endOfUnicode < source.length) {
+ end = endOfUnicode;
+ } else {
+ return false; // not enough characters to decode an unicode
+ }
+ }
+
+ if ((c1 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c1 < 0
+ || (c2 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c2 < 0
+ || (c3 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c3 < 0
+ || (c4 = ScannerHelper.getNumericValue(source[pos++])) > 15
+ || c4 < 0) {
+ return false;
+ } else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ nextCharacterPosition = pos;
+ }
+ } else {
+ currentCharacter = source[currentPosition];
+ nextCharacterPosition = currentPosition+1;
+ }
+
+ switch(currentCharacter) {
+ case '\r':
+ case '\n':
+ case '/':
+ case '"':
+ case '\'':
+ brokeLoop=true;
+ break lineLoop;
+ }
+ currentPosition--;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return false;
+ }
+ if (!brokeLoop)
+ nextCharacterPosition=currentPosition;
+
+ // compute start and end of the last token
+ scanner.resetTo(nextCharacterPosition, end);
+ do {
+ try {
+ token = scanner.getNextToken();
+ } catch (InvalidInputException e) {
+ return false;
+ }
+ switch (token) {
+ case TerminalTokens.TokenNamethis:
+ case TerminalTokens.TokenNamesuper:
+ case TerminalTokens.TokenNameIdentifier:
+ if (scanner.startPosition <= selectionStart && selectionStart <= scanner.currentPosition) {
+ if (scanner.currentPosition == scanner.eofPosition) {
+ int temp = scanner.eofPosition;
+ scanner.eofPosition = scanner.source.length;
+ while(scanner.getNextCharAsJavaIdentifierPart()){/*empty*/}
+ scanner.eofPosition = temp;
+ }
+ lastIdentifierStart = scanner.startPosition;
+ lastIdentifierEnd = scanner.currentPosition - 1;
+ lastIdentifier = scanner.getCurrentTokenSource();
+ }
+ break;
+ }
+ } while (token != TerminalTokens.TokenNameEOF);
+ } else {
+ scanner.resetTo(selectionStart, selectionEnd);
+
+ boolean expectingIdentifier = true;
+ try {
+ do {
+ token = scanner.getNextToken();
+
+ switch (token) {
+ case TerminalTokens.TokenNamethis :
+ case TerminalTokens.TokenNamesuper :
+ case TerminalTokens.TokenNameIdentifier :
+ if (!expectingIdentifier)
+ return false;
+ lastIdentifier = scanner.getCurrentTokenSource();
+ lastIdentifierStart = scanner.startPosition;
+ lastIdentifierEnd = scanner.currentPosition - 1;
+ if(lastIdentifierEnd > selectionEnd) {
+ lastIdentifierEnd = selectionEnd;
+ lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1);
+ }
+
+ expectingIdentifier = false;
+ break;
+ case TerminalTokens.TokenNameDOT :
+ if (expectingIdentifier)
+ return false;
+ expectingIdentifier = true;
+ break;
+ case TerminalTokens.TokenNameEOF :
+ if (expectingIdentifier)
+ return false;
+ break;
+ case TerminalTokens.TokenNameLESS :
+ if(!checkTypeArgument(scanner))
+ return false;
+ break;
+ default :
+ return false;
+ }
+ } while (token != TerminalTokens.TokenNameEOF);
+ } catch (InvalidInputException e) {
+ return false;
+ }
+ }
+ if (lastIdentifierStart >= 0) {
+ this.actualSelectionStart = lastIdentifierStart;
+ this.actualSelectionEnd = lastIdentifierEnd;
+ this.selectedIdentifier = lastIdentifier;
+ return true;
+ }
+ return false;
+ }
+ private boolean checkTypeArgument(Scanner scanner) throws InvalidInputException {
+ int depth = 1;
+ int token;
+ StringBuffer buffer = new StringBuffer();
+ do {
+ token = scanner.getNextToken();
+
+ switch(token) {
+ case TerminalTokens.TokenNameLESS :
+ depth++;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameGREATER :
+ depth--;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameRIGHT_SHIFT :
+ depth-=2;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
+ depth-=3;
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+ case TerminalTokens.TokenNameextends :
+ case TerminalTokens.TokenNamesuper :
+ buffer.append(' ');
+ buffer.append(scanner.getCurrentTokenSource());
+ buffer.append(' ');
+ break;
+ case TerminalTokens.TokenNameCOMMA :
+ if(depth == 1) {
+ int length = buffer.length();
+ char[] typeRef = new char[length];
+ buffer.getChars(0, length, typeRef, 0);
+ try {
+ Signature.createTypeSignature(typeRef, true);
+ buffer = new StringBuffer();
+ } catch(IllegalArgumentException e) {
+ return false;
+ }
+ }
+ break;
+ default :
+ buffer.append(scanner.getCurrentTokenSource());
+ break;
+
+ }
+ if(depth < 0) {
+ return false;
+ }
+ } while (depth != 0 && token != TerminalTokens.TokenNameEOF);
+
+ if(depth == 0) {
+ int length = buffer.length() - 1;
+ char[] typeRef = new char[length];
+ buffer.getChars(0, length, typeRef, 0);
+ try {
+ Signature.createTypeSignature(typeRef, true);
+ return true;
+ } catch(IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ public AssistParser getParser() {
+ return this.parser;
+ }
+
+ /*
+ * Returns whether the given binding is a local/anonymous reference binding, or if its declaring class is
+ * local.
+ */
+ private boolean isLocal(ReferenceBinding binding) {
+ if (!(binding instanceof SourceTypeBinding)) return false;
+ if (binding instanceof LocalTypeBinding) return true;
+ if (binding instanceof MemberTypeBinding) {
+ return isLocal(((MemberTypeBinding)binding).enclosingType);
+ }
+ return false;
+ }
+
+ /**
+ * Ask the engine to compute the selection at the specified position
+ * of the given compilation unit.
+
+ * @param sourceUnit org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit
+ * the source of the current compilation unit.
+ *
+ * @param selectionSourceStart int
+ * @param selectionSourceEnd int
+ * a range in the source where the selection is.
+ */
+ public void select(
+ ICompilationUnit sourceUnit,
+ int selectionSourceStart,
+ int selectionSourceEnd) {
+
+ char[] source = sourceUnit.getContents();
+
+ if(DEBUG) {
+ System.out.print("SELECTION IN "); //$NON-NLS-1$
+ System.out.print(sourceUnit.getFileName());
+ System.out.print(" FROM "); //$NON-NLS-1$
+ System.out.print(selectionSourceStart);
+ System.out.print(" TO "); //$NON-NLS-1$
+ System.out.println(selectionSourceEnd);
+ System.out.println("SELECTION - Source :"); //$NON-NLS-1$
+ System.out.println(source);
+ }
+ if (!checkSelection(source, selectionSourceStart, selectionSourceEnd)) {
+ return;
+ }
+ if (DEBUG) {
+ System.out.print("SELECTION - Checked : \""); //$NON-NLS-1$
+ System.out.print(new String(source, actualSelectionStart, actualSelectionEnd-actualSelectionStart+1));
+ System.out.println('"');
+ }
+ try {
+ this.acceptedAnswer = false;
+ CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit =
+ this.parser.dietParse(sourceUnit, result, this.actualSelectionStart, this.actualSelectionEnd);
+
+ if (parsedUnit != null) {
+ if(DEBUG) {
+ System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+
+ // check for inferred types declared with their names in the selection
+ this.parser.inferTypes(parsedUnit, this.compilerOptions);
+ for (int i = 0; i < parsedUnit.inferredTypes.length; i++) {
+ if (parsedUnit.inferredTypes[i] != null && parsedUnit.inferredTypes[i].isDefinition && parsedUnit.inferredTypes[i].getNameStart() <= selectionSourceEnd && selectionSourceStart <= parsedUnit.inferredTypes[i].getNameStart() + parsedUnit.inferredTypes[i].getName().length) {
+ this.requestor.acceptType(CharOperation.NO_CHAR, sourceUnit.getFileName(), parsedUnit.inferredTypes[i].getName(), 0, parsedUnit.inferredTypes[i].isDefinition, CharOperation.NO_CHAR, parsedUnit.inferredTypes[i].sourceStart, parsedUnit.inferredTypes[i].sourceEnd);
+ }
+ }
+ // scan the package & import statements first
+ if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) {
+ char[][] tokens =
+ ((SelectionOnPackageReference) parsedUnit.currentPackage).tokens;
+ this.noProposal = false;
+ this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+ return;
+ }
+ ImportReference[] imports = parsedUnit.imports;
+ if (imports != null) {
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportReference importReference = imports[i];
+ if (importReference instanceof SelectionOnImportReference) {
+ char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
+ this.noProposal = false;
+ this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+ this.nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), false, false, IJavaScriptSearchConstants.TYPE, this);
+
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ int tokenCount = tokens.length;
+ char[] lastToken = tokens[tokenCount - 1];
+ char[][] qualifierTokens = CharOperation.subarray(tokens, 0, tokenCount - 1);
+
+ if(qualifierTokens != null && qualifierTokens.length > 0) {
+ Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens);
+ if(binding != null && binding instanceof ReferenceBinding) {
+ ReferenceBinding ref = (ReferenceBinding) binding;
+ selectMemberTypeFromImport(parsedUnit, lastToken, ref);
+ }
+ }
+ }
+
+ // accept qualified types only if no unqualified type was accepted
+ if(!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ if (!this.acceptedAnswer) {
+ this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaScriptSearchConstants.TYPE, this);
+ // try with simple type name
+ if(!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ }
+ }
+ }
+ if(this.noProposal && this.problem != null) {
+ this.requestor.acceptError(this.problem);
+ }
+ return;
+ }
+ }
+ }
+ if (parsedUnit.statements != null || parsedUnit.isPackageInfo()) {
+ if(selectDeclaration(parsedUnit))
+ return;
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ try {
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+ parsedUnit.scope.faultInTypes();
+ ASTNode node = null;
+ if (parsedUnit.types != null)
+ node = parseBlockStatements(parsedUnit, selectionSourceStart);
+ if(DEBUG) {
+ System.out.println("SELECTION - AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+ parsedUnit.resolve();
+ if (node != null) {
+ selectLocalDeclaration(node);
+ }
+ } catch (SelectionNodeFound e) {
+ if (e.binding != null) {
+ if(DEBUG) {
+ System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$
+ System.out.println(e.binding.toString());
+ }
+ // if null then we found a problem in the selection node
+ selectFrom(e.binding, parsedUnit, e.isDeclaration);
+ }
+ }
+ }
+ }
+ }
+ // only reaches here if no selection could be derived from the parsed tree
+ // thus use the selected source and perform a textual type search
+ if (!this.acceptedAnswer) {
+ this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaScriptSearchConstants.TYPE, this);
+
+ // accept qualified types only if no unqualified type was accepted
+ if(!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ }
+ }
+ if(this.noProposal && this.problem != null) {
+ this.requestor.acceptError(this.problem);
+ }
+ } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
+ if(DEBUG) {
+ System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+ if(DEBUG) {
+ System.out.println("Exception caught by SelectionEngine:"); //$NON-NLS-1$
+ e.printStackTrace(System.out);
+ }
+ } finally {
+ reset();
+ }
+ }
+
+ private void selectMemberTypeFromImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref) {
+ int fieldLength = lastToken.length;
+ ReferenceBinding[] memberTypes = ref.memberTypes();
+ next : for (int j = 0; j < memberTypes.length; j++) {
+ ReferenceBinding memberType = memberTypes[j];
+
+ if (fieldLength > memberType.sourceName.length)
+ continue next;
+
+ if (!CharOperation.equals(lastToken, memberType.sourceName, true))
+ continue next;
+
+ this.selectFrom(memberType, parsedUnit, false);
+ }
+ }
+
+ private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit, boolean isDeclaration) {
+ if (binding instanceof ReferenceBinding) {
+ ReferenceBinding typeBinding = (ReferenceBinding) binding;
+ if(typeBinding instanceof ProblemReferenceBinding) {
+ typeBinding = typeBinding.closestMatch();
+ }
+ if (typeBinding == null) return;
+ if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
+ this.noProposal = false;
+ ((SelectionRequestor)this.requestor).acceptLocalType(typeBinding);
+ } else {
+ this.noProposal = false;
+
+ this.requestor.acceptType(
+ typeBinding.qualifiedPackageName(),
+ typeBinding.getFileName(),
+ typeBinding.qualifiedSourceName(),
+ typeBinding.modifiers,
+ false,
+ typeBinding.computeUniqueKey(),
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedAnswer = true;
+ } else
+ if (binding instanceof MethodBinding) {
+ MethodBinding methodBinding = (MethodBinding) binding;
+ this.noProposal = false;
+
+ boolean isValuesOrValueOf = false;
+
+ if(!isValuesOrValueOf) {
+ TypeBinding[] parameterTypes = methodBinding.original().parameters;
+ int length = parameterTypes.length;
+ char[][] parameterPackageNames = new char[length][];
+ char[][] parameterTypeNames = new char[length][];
+ String[] parameterSignatures = new String[length];
+ for (int i = 0; i < length; i++) {
+ parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName();
+ parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
+ parameterSignatures[i] = new String(getSignature(parameterTypes[i])).replace('/', '.');
+ }
+
+ char[][] typeParameterNames = new char[length][];
+ char[][][] typeParameterBoundNames = new char[length][][];
+
+ ReferenceBinding declaringClass = methodBinding.declaringClass;
+ if ( ( ( methodBinding instanceof LocalFunctionBinding || isLocal(declaringClass))
+ && this.requestor instanceof SelectionRequestor)
+ || declaringClass.qualifiedSourceName()==null) {
+ ((SelectionRequestor)this.requestor).acceptLocalMethod(methodBinding);
+ } else {
+ this.requestor.acceptMethod(
+ /*declaringClass.qualifiedPackageName()*/ new char[0],
+ declaringClass.getFileName(),
+ declaringClass.qualifiedSourceName(),
+ declaringClass.enclosingType() == null ? null : new String(getSignature(declaringClass.enclosingType())),
+ methodBinding.isConstructor()
+ ? declaringClass.sourceName()
+ : methodBinding.selector,
+ parameterPackageNames,
+ parameterTypeNames,
+ parameterSignatures,
+ typeParameterNames,
+ typeParameterBoundNames,
+ methodBinding.isConstructor(),
+ isDeclaration,
+ methodBinding.computeUniqueKey(),
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ }
+ this.acceptedAnswer = true;
+ } else
+ if (binding instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding) binding;
+ ReferenceBinding declaringClass = fieldBinding.declaringClass;
+ if (declaringClass != null) { // arraylength
+ this.noProposal = false;
+ if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
+ ((SelectionRequestor)this.requestor).acceptLocalField(fieldBinding);
+ } else {
+ this.requestor.acceptField(
+ declaringClass.qualifiedPackageName(),
+ declaringClass.getFileName(),
+ declaringClass.qualifiedSourceName(),
+ fieldBinding.name,
+ false,
+ (fieldBinding.methodBinding == null) ? fieldBinding.computeUniqueKey() : fieldBinding.methodBinding.computeUniqueKey(),
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+ }
+ this.acceptedAnswer = true;
+ }
+ } else
+ if (binding instanceof LocalVariableBinding) {
+ this.noProposal = false;
+ if (this.requestor instanceof SelectionRequestor) {
+ ((SelectionRequestor)this.requestor).acceptLocalVariable((LocalVariableBinding)binding);
+ this.acceptedAnswer = true;
+ } else {
+ // open on the type of the variable
+ selectFrom(((LocalVariableBinding) binding).type, parsedUnit, false);
+ }
+ } else
+ if (binding instanceof ArrayBinding) {
+ selectFrom(((ArrayBinding) binding).leafComponentType, parsedUnit, false);
+ // open on the type of the array
+ } else
+ if (binding instanceof PackageBinding) {
+ PackageBinding packageBinding = (PackageBinding) binding;
+ this.noProposal = false;
+ this.requestor.acceptPackage(packageBinding.readableName());
+ this.acceptedAnswer = true;
+ } else
+ if(binding instanceof BaseTypeBinding) {
+ this.acceptedAnswer = true;
+ }
+ }
+
+ /*
+ * Checks if a local declaration got selected in this method/initializer/field.
+ */
+ private void selectLocalDeclaration(ASTNode node) {
+ // the selected identifier is not identical to the parser one (equals but not identical),
+ // for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
+ final char[] assistIdentifier = this.getParser().assistIdentifier();
+ if (assistIdentifier == null) return;
+
+ class Visitor extends ASTVisitor {
+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+ if (constructorDeclaration.selector == assistIdentifier){
+ if (constructorDeclaration.binding != null) {
+ throw new SelectionNodeFound(constructorDeclaration.binding);
+ } else {
+ if (constructorDeclaration.scope != null) {
+ throw new SelectionNodeFound(new MethodBinding(constructorDeclaration.modifiers, constructorDeclaration.selector, null, null, constructorDeclaration.scope.referenceType().binding));
+ }
+ }
+ }
+ return true;
+ }
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ if (fieldDeclaration.name == assistIdentifier){
+ throw new SelectionNodeFound(fieldDeclaration.binding);
+ }
+ return true;
+ }
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ if (localTypeDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(localTypeDeclaration.binding);
+ }
+ return true;
+ }
+ public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+ if (memberTypeDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(memberTypeDeclaration.binding);
+ }
+ return true;
+ }
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ if (methodDeclaration.selector == assistIdentifier){
+ if (methodDeclaration.binding != null) {
+ throw new SelectionNodeFound(methodDeclaration.binding);
+ } else {
+ if (methodDeclaration.scope != null) {
+ throw new SelectionNodeFound(new MethodBinding(methodDeclaration.modifiers, methodDeclaration.selector, null, null, methodDeclaration.scope.referenceType().binding));
+ }
+ }
+ }
+ return true;
+ }
+ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+ if (typeDeclaration.name == assistIdentifier) {
+ throw new SelectionNodeFound(typeDeclaration.binding);
+ }
+ return true;
+ }
+ }
+
+ if (node instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration)node).traverse(new Visitor(), (ClassScope)null);
+ } else {
+ ((FieldDeclaration)node).traverse(new Visitor(), (MethodScope)null);
+ }
+ }
+
+ /**
+ * Asks the engine to compute the selection of the given type
+ * from the source type.
+ *
+ * @param sourceType org.eclipse.wst.jsdt.internal.compiler.env.ISourceType
+ * a source form of the current type in which code assist is invoked.
+ *
+ * @param typeName char[]
+ * a type name which is to be resolved in the context of a compilation unit.
+ * NOTE: the type name is supposed to be correctly reduced (no whitespaces, no unicodes left)
+ *
+ * @param topLevelTypes SourceTypeElementInfo[]
+ * a source form of the top level types of the compilation unit in which code assist is invoked.
+
+ * @param searchInEnvironment
+ * if true
and no selection could be found in context then search type in environment.
+ */
+ public void selectType(ISourceType sourceType, char[] typeName, SourceTypeElementInfo[] topLevelTypes, boolean searchInEnvironment) {
+ try {
+ this.acceptedAnswer = false;
+
+ // only the type erasure are returned by IType.resolvedType(...)
+ if (CharOperation.indexOf('<', typeName) != -1) {
+ char[] typeSig = Signature.createCharArrayTypeSignature(typeName, false/*not resolved*/);
+ typeName = Signature.toCharArray(typeSig);
+ }
+
+ // find the outer most type
+ ISourceType outerType = sourceType;
+ ISourceType parent = sourceType.getEnclosingType();
+ while (parent != null) {
+ outerType = parent;
+ parent = parent.getEnclosingType();
+ }
+ // compute parse tree for this most outer type
+ CompilationResult result = new CompilationResult(outerType.getFileName(), outerType.getPackageName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ if (!(sourceType instanceof SourceTypeElementInfo)) return;
+ SourceType typeHandle = (SourceType) ((SourceTypeElementInfo)sourceType).getHandle();
+ int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE;
+ if (typeHandle.isAnonymous() || typeHandle.isLocal())
+ flags |= SourceTypeConverter.LOCAL_TYPE;
+ CompilationUnitDeclaration parsedUnit =
+ SourceTypeConverter.buildCompilationUnit(
+ topLevelTypes,
+ flags,
+ this.parser.problemReporter(),
+ result);
+
+ if (parsedUnit != null && parsedUnit.types != null) {
+ if(DEBUG) {
+ System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
+ System.out.println(parsedUnit.toString());
+ }
+ // find the type declaration that corresponds to the original source type
+ TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(typeHandle);
+
+ if (typeDecl != null) {
+
+ // add fake field with the type we're looking for
+ // note: since we didn't ask for fields above, there is no field defined yet
+ FieldDeclaration field = new FieldDeclaration();
+ int dot;
+ if ((dot = CharOperation.lastIndexOf('.', typeName)) == -1) {
+ this.selectedIdentifier = typeName;
+ field.type = new SelectionOnSingleTypeReference(typeName, -1);
+ // position not used
+ } else {
+ char[][] previousIdentifiers = CharOperation.splitOn('.', typeName, 0, dot);
+ char[] selectionIdentifier =
+ CharOperation.subarray(typeName, dot + 1, typeName.length);
+ this.selectedIdentifier = selectionIdentifier;
+ field.type =
+ new SelectionOnQualifiedTypeReference(
+ previousIdentifiers,
+ selectionIdentifier,
+ new long[previousIdentifiers.length + 1]);
+ }
+ field.name = "".toCharArray(); //$NON-NLS-1$
+ typeDecl.fields = new FieldDeclaration[] { field };
+
+ // build bindings
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ try {
+ // build fields
+ // note: this builds fields only in the parsed unit (the buildFieldsAndMethods flag is not passed along)
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+
+ // resolve
+ parsedUnit.scope.faultInTypes();
+ parsedUnit.resolve();
+ } catch (SelectionNodeFound e) {
+ if (e.binding != null) {
+ if(DEBUG) {
+ System.out.println("SELECTION - Selection binding :"); //$NON-NLS-1$
+ System.out.println(e.binding.toString());
+ }
+ // if null then we found a problem in the selection node
+ selectFrom(e.binding, parsedUnit, e.isDeclaration);
+ }
+ }
+ }
+ }
+ }
+ // only reaches here if no selection could be derived from the parsed tree
+ // thus use the selected source and perform a textual type search
+ if (!this.acceptedAnswer && searchInEnvironment) {
+ if (this.selectedIdentifier != null) {
+ this.nameEnvironment.findTypes(typeName, false, false, IJavaScriptSearchConstants.TYPE, this);
+
+ // accept qualified types only if no unqualified type was accepted
+ if(!this.acceptedAnswer) {
+ acceptQualifiedTypes();
+ }
+ }
+ }
+ if(this.noProposal && this.problem != null) {
+ this.requestor.acceptError(this.problem);
+ }
+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+ } finally {
+ reset();
+ }
+ }
+
+ // Check if a declaration got selected in this unit
+ private boolean selectDeclaration(CompilationUnitDeclaration compilationUnit){
+
+ // the selected identifier is not identical to the parser one (equals but not identical),
+ // for traversing the parse tree, the parser assist identifier is necessary for identity checks
+ char[] assistIdentifier = this.getParser().assistIdentifier();
+ if (assistIdentifier == null) return false;
+
+ ImportReference currentPackage = compilationUnit.currentPackage;
+ char[] packageName = currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(currentPackage.tokens, '.');
+ // iterate over the types
+ TypeDeclaration[] types = compilationUnit.types;
+ for (int i = 0, length = types == null ? 0 : types.length; i < length; i++){
+ if(selectDeclaration(types[i], assistIdentifier, packageName))
+ return true;
+ }
+ ProgramElement[] statements = compilationUnit.statements;
+ for (int i = 0, length = statements == null ? 0 : statements.length; i < length; i++){
+ if (statements[i] instanceof FieldDeclaration)
+ {
+ FieldDeclaration field = (FieldDeclaration)statements[i];
+
+ if (field.name == assistIdentifier){
+ char[] qualifiedSourceName = null;
+
+ this.requestor.acceptField(
+ packageName,
+ compilationUnit.getFileName(),
+ qualifiedSourceName,
+ field.name,
+ true,
+ field.binding != null ? field.binding.computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+ }
+ else if (statements[i] instanceof AbstractMethodDeclaration)
+ {
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration)statements[i];
+
+ if (method.selector == assistIdentifier){
+ char[] qualifiedSourceName = compilationUnit.getFileName();
+
+ this.requestor.acceptMethod(
+ packageName,
+ compilationUnit.getFileName(),
+ qualifiedSourceName,
+ null, // SelectionRequestor does not need of declaring type signature for method declaration
+ method.selector,
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null,null,
+ method.isConstructor(),
+ true,
+ method.binding != null ? method.binding.computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+
+ }
+
+ }
+ return false;
+ }
+
+ // Check if a declaration got selected in this type
+ private boolean selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier, char[] packageName){
+
+ if (typeDeclaration.name == assistIdentifier){
+ char[] qualifiedSourceName = null;
+
+ TypeDeclaration enclosingType = typeDeclaration;
+ while(enclosingType != null) {
+ qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+ enclosingType = enclosingType.enclosingType;
+ }
+ char[] uniqueKey = typeDeclaration.binding != null ? typeDeclaration.binding.computeUniqueKey() : null;
+
+ this.requestor.acceptType(
+ packageName,
+ null,
+ qualifiedSourceName,
+ typeDeclaration.modifiers,
+ true,
+ uniqueKey,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+ TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+ for (int i = 0, length = memberTypes == null ? 0 : memberTypes.length; i < length; i++){
+ if(selectDeclaration(memberTypes[i], assistIdentifier, packageName))
+ return true;
+ }
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ for (int i = 0, length = fields == null ? 0 : fields.length; i < length; i++){
+ if (fields[i].name == assistIdentifier){
+ char[] qualifiedSourceName = null;
+
+ TypeDeclaration enclosingType = typeDeclaration;
+ while(enclosingType != null) {
+ qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+ enclosingType = enclosingType.enclosingType;
+ }
+ FieldDeclaration field = fields[i];
+ this.requestor.acceptField(
+ packageName,
+ null,
+ qualifiedSourceName,
+ field.name,
+ true,
+ field.binding != null ? field.binding.computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+ }
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++){
+ AbstractMethodDeclaration method = methods[i];
+
+ if (method.selector == assistIdentifier){
+ char[] qualifiedSourceName = null;
+
+ TypeDeclaration enclosingType = typeDeclaration;
+ while(enclosingType != null) {
+ qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.');
+ enclosingType = enclosingType.enclosingType;
+ }
+
+ this.requestor.acceptMethod(
+ packageName,
+ null,
+ qualifiedSourceName,
+ null, // SelectionRequestor does not need of declaring type signature for method declaration
+ method.selector,
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of parameters type for method declaration
+ null, // SelectionRequestor does not need of type parameters name for method declaration
+ null, // SelectionRequestor does not need of type parameters bounds for method declaration
+ method.isConstructor(),
+ true,
+ method.binding != null ? method.binding.computeUniqueKey() : null,
+ this.actualSelectionStart,
+ this.actualSelectionEnd);
+
+ this.noProposal = false;
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+ public CompilationUnitDeclaration doParse(ICompilationUnit unit, AccessRestriction accessRestriction) {
+ CompilationResult unitResult =
+ new CompilationResult(unit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ try {
+ Parser localParser = new Parser(this.parser.problemReporter(), this.compilerOptions.parseLiteralExpressionsAsConstants);
+
+ CompilationUnitDeclaration parsedUnit = localParser.parse(unit, unitResult);
+ localParser.inferTypes(parsedUnit,this.compilerOptions);
+ return parsedUnit;
+ } catch (AbortCompilationUnit e) {
+// // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+// // one requested further along to resolve sourceUnit.
+// if (unitResult.compilationUnit == sourceUnit) { // only report once
+// requestor.acceptResult(unitResult.tagAsAccepted());
+// } else {
+ throw e; // want to abort enclosing request to compile
+// }
+ }
+
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ThrownExceptionFinder.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ThrownExceptionFinder.java
new file mode 100644
index 0000000..28f2bbd
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/ThrownExceptionFinder.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import java.util.Stack;
+
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.util.SimpleSet;
+
+public class ThrownExceptionFinder extends ASTVisitor {
+
+ private SimpleSet thrownExceptions;
+ private Stack exceptionsStack;
+
+ public ReferenceBinding[] find(TryStatement tryStatement, BlockScope scope) {
+ this.thrownExceptions = new SimpleSet();
+ this.exceptionsStack = new Stack();
+ tryStatement.traverse(this, scope);
+ removeCaughtExceptions(tryStatement);
+
+ ReferenceBinding[] result = new ReferenceBinding[this.thrownExceptions.elementSize];
+ this.thrownExceptions.asArray(result);
+ return result;
+ }
+
+ private void acceptException(ReferenceBinding binding) {
+ if (binding != null && binding.isValidBinding()) {
+ this.thrownExceptions.add(binding);
+ }
+ }
+
+ public void endVisit(MessageSend messageSend, BlockScope scope) {
+ super.endVisit(messageSend, scope);
+ }
+
+ public void endVisit(AllocationExpression allocationExpression, BlockScope scope) {
+ super.endVisit(allocationExpression, scope);
+ }
+
+ public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
+ this.acceptException((ReferenceBinding)throwStatement.exception.resolvedType);
+ super.endVisit(throwStatement, scope);
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+ return this.visitType(typeDeclaration);
+ }
+
+ public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+ return this.visitType(memberTypeDeclaration);
+ }
+
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+ return this.visitType(localTypeDeclaration);
+ }
+
+ private boolean visitType(TypeDeclaration typeDeclaration) {
+ return false;
+ }
+
+ public boolean visit(TryStatement tryStatement, BlockScope scope) {
+ this.exceptionsStack.push(this.thrownExceptions);
+ SimpleSet exceptionSet = new SimpleSet();
+ this.thrownExceptions = exceptionSet;
+ tryStatement.tryBlock.traverse(this, scope);
+
+ this.removeCaughtExceptions(tryStatement);
+
+ this.thrownExceptions = (SimpleSet)this.exceptionsStack.pop();
+
+ Object[] values = exceptionSet.values;
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] != null) {
+ this.thrownExceptions.add(values[i]);
+ }
+ }
+
+ Block[] catchBlocks = tryStatement.catchBlocks;
+ int length = catchBlocks == null ? 0 : catchBlocks.length;
+ for (int i = 0; i < length; i++) {
+ catchBlocks[i].traverse(this, scope);
+ }
+ return false;
+ }
+
+ private void removeCaughtExceptions(TryStatement tryStatement) {
+ Argument[] catchArguments = tryStatement.catchArguments;
+ int length = catchArguments == null ? 0 : catchArguments.length;
+ for (int i = 0; i < length; i++) {
+ TypeBinding exception = catchArguments[i].type.resolvedType;
+ if (exception != null && exception.isValidBinding()) {
+ this.removeCaughtException((ReferenceBinding)exception);
+
+ }
+ }
+ }
+
+ private void removeCaughtException(ReferenceBinding caughtException) {
+ Object[] exceptions = this.thrownExceptions.values;
+ for (int i = 0; i < exceptions.length; i++) {
+ ReferenceBinding exception = (ReferenceBinding)exceptions[i];
+ if (exception != null) {
+ if (exception == caughtException || caughtException.isSuperclassOf(exception)) {
+ this.thrownExceptions.remove(exception);
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/UnresolvedReferenceNameFinder.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/UnresolvedReferenceNameFinder.java
new file mode 100644
index 0000000..c7c3744
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/UnresolvedReferenceNameFinder.java
@@ -0,0 +1,552 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionParser;
+import org.eclipse.wst.jsdt.internal.codeassist.complete.CompletionScanner;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Statement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.util.SimpleSetOfCharArray;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+public class UnresolvedReferenceNameFinder extends ASTVisitor {
+ private static final int MAX_LINE_COUNT = 100;
+ private static final int FAKE_BLOCKS_COUNT = 20;
+
+ public static interface UnresolvedReferenceNameRequestor {
+ public void acceptName(char[] name);
+ }
+
+ private UnresolvedReferenceNameRequestor requestor;
+
+ private CompletionEngine completionEngine;
+ private CompletionParser parser;
+ private CompletionScanner completionScanner;
+
+ private int parentsPtr;
+ private ASTNode[] parents;
+
+ private int potentialVariableNamesPtr;
+ private char[][] potentialVariableNames;
+ private int[] potentialVariableNameStarts;
+
+ private SimpleSetOfCharArray acceptedNames = new SimpleSetOfCharArray();
+
+ public UnresolvedReferenceNameFinder(CompletionEngine completionEngine) {
+ this.completionEngine = completionEngine;
+ this.parser = completionEngine.parser;
+ this.completionScanner = (CompletionScanner) parser.scanner;
+ }
+
+ private void acceptName(char[] name) {
+ // the null check is added to fix bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=166570
+ if (name == null) return;
+
+ if (!CharOperation.prefixEquals(this.completionEngine.completionToken, name, false /* ignore case */)
+ && !(this.completionEngine.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionEngine.completionToken, name))) return;
+
+ if (acceptedNames.includes(name)) return;
+
+ this.acceptedNames.add(name);
+
+ // accept result
+ this.requestor.acceptName(name);
+ }
+
+ public void find(
+ char[] startWith,
+ Initializer initializer,
+ ClassScope scope,
+ int from,
+ char[][] discouragedNames,
+ UnresolvedReferenceNameRequestor nameRequestor) {
+ MethodDeclaration fakeMethod =
+ this.findAfter(startWith, scope, from, initializer.bodyEnd, MAX_LINE_COUNT, false, discouragedNames, nameRequestor);
+ if (fakeMethod != null) fakeMethod.traverse(this, scope);
+ }
+
+ public void find(
+ char[] startWith,
+ AbstractMethodDeclaration methodDeclaration,
+ int from,
+ char[][] discouragedNames,
+ UnresolvedReferenceNameRequestor nameRequestor) {
+ MethodDeclaration fakeMethod =
+ this.findAfter(startWith, methodDeclaration.scope, from, methodDeclaration.bodyEnd, MAX_LINE_COUNT, false, discouragedNames, nameRequestor);
+ if (fakeMethod != null) fakeMethod.traverse(this, methodDeclaration.scope.classScope());
+ }
+
+ public void findAfter(
+ char[] startWith,
+ Scope scope,
+ ClassScope classScope,
+ int from,
+ int to,
+ char[][] discouragedNames,
+ UnresolvedReferenceNameRequestor nameRequestor) {
+ MethodDeclaration fakeMethod =
+ this.findAfter(startWith, scope, from, to, MAX_LINE_COUNT / 2, true, discouragedNames, nameRequestor);
+ if (fakeMethod != null) fakeMethod.traverse(this, classScope);
+ }
+
+ private MethodDeclaration findAfter(
+ char[] startWith,
+ Scope s,
+ int from,
+ int to,
+ int maxLineCount,
+ boolean outsideEnclosingBlock,
+ char[][] discouragedNames,
+ UnresolvedReferenceNameRequestor nameRequestor) {
+ this.requestor = nameRequestor;
+
+ // reinitialize completion scanner to be usable as a normal scanner
+ this.completionScanner.cursorLocation = 0;
+
+ if (!outsideEnclosingBlock) {
+ // compute location of the end of the current block
+ this.completionScanner.resetTo(from + 1, to);
+ this.completionScanner.jumpOverBlock();
+
+ to = this.completionScanner.startPosition - 1;
+ }
+
+ int maxEnd =
+ this.completionScanner.getLineEnd(
+ Util.getLineNumber(from, this.completionScanner.lineEnds, 0, this.completionScanner.linePtr) + maxLineCount);
+
+ int end;
+ if (maxEnd < 0) {
+ end = to;
+ } else {
+ end = maxEnd < to ? maxEnd : to;
+ }
+
+ this.parser.startRecordingIdentifiers(from, end);
+
+ MethodDeclaration fakeMethod = this.parser.parseSomeStatements(
+ from,
+ end,
+ outsideEnclosingBlock ? FAKE_BLOCKS_COUNT : 0,
+ s.compilationUnitScope().referenceContext);
+
+ this.parser.stopRecordingIdentifiers();
+
+ if(!this.initPotentialNamesTables(discouragedNames)) return null;
+
+ this.parentsPtr = -1;
+ this.parents = new ASTNode[10];
+
+ return fakeMethod;
+ }
+
+ public void findBefore(
+ char[] startWith,
+ Scope scope,
+ ClassScope classScope,
+ int from,
+ int recordTo,
+ int parseTo,
+ char[][] discouragedNames,
+ UnresolvedReferenceNameRequestor nameRequestor) {
+ MethodDeclaration fakeMethod =
+ this.findBefore(startWith, scope, from, recordTo, parseTo, MAX_LINE_COUNT / 2, discouragedNames, nameRequestor);
+ if (fakeMethod != null) fakeMethod.traverse(this, classScope);
+ }
+
+ private MethodDeclaration findBefore(
+ char[] startWith,
+ Scope s,
+ int from,
+ int recordTo,
+ int parseTo,
+ int maxLineCount,
+ char[][] discouragedNames,
+ UnresolvedReferenceNameRequestor nameRequestor) {
+ this.requestor = nameRequestor;
+
+ // reinitialize completion scanner to be usable as a normal scanner
+ this.completionScanner.cursorLocation = 0;
+
+ int minStart =
+ this.completionScanner.getLineStart(
+ Util.getLineNumber(recordTo, this.completionScanner.lineEnds, 0, this.completionScanner.linePtr) - maxLineCount);
+
+ int start;
+ int fakeBlocksCount;
+ if (minStart <= from) {
+ start = from;
+ fakeBlocksCount = 0;
+ } else {
+ start = minStart;
+ fakeBlocksCount = FAKE_BLOCKS_COUNT;
+ }
+
+ this.parser.startRecordingIdentifiers(start, recordTo);
+
+ MethodDeclaration fakeMethod = this.parser.parseSomeStatements(
+ start,
+ parseTo,
+ fakeBlocksCount,
+ s.compilationUnitScope().referenceContext);
+
+ this.parser.stopRecordingIdentifiers();
+
+ if(!this.initPotentialNamesTables(discouragedNames)) return null;
+
+ this.parentsPtr = -1;
+ this.parents = new ASTNode[10];
+
+ return fakeMethod;
+ }
+
+ private boolean initPotentialNamesTables(char[][] discouragedNames) {
+ char[][] pvns = this.parser.potentialVariableNames;
+ int[] pvnss = this.parser.potentialVariableNameStarts;
+ int pvnsPtr = this.parser.potentialVariableNamesPtr;
+
+ if (pvnsPtr < 0) return false; // there is no potential names
+
+ // remove null and discouragedNames
+ int discouragedNamesCount = discouragedNames == null ? 0 : discouragedNames.length;
+ int j = -1;
+ next : for (int i = 0; i <= pvnsPtr; i++) {
+ char[] temp = pvns[i];
+
+ if (temp == null) continue next;
+
+ for (int k = 0; k < discouragedNamesCount; k++) {
+ if (CharOperation.equals(temp, discouragedNames[k], false)) {
+ continue next;
+ }
+ }
+
+ pvns[i] = null;
+ pvns[++j] = temp;
+ pvnss[j] = pvnss[i];
+ }
+ pvnsPtr = j;
+
+ if (pvnsPtr < 0) return false; // there is no potential names
+
+ this.potentialVariableNames = pvns;
+ this.potentialVariableNameStarts = pvnss;
+ this.potentialVariableNamesPtr = pvnsPtr;
+
+ return true;
+ }
+
+ private void popParent() {
+ this.parentsPtr--;
+ }
+ private void pushParent(ASTNode parent) {
+ int length = this.parents.length;
+ if (this.parentsPtr >= length - 1) {
+ System.arraycopy(this.parents, 0, this.parents = new ASTNode[length * 2], 0, length);
+ }
+ this.parents[++this.parentsPtr] = parent;
+ }
+
+ private ASTNode getEnclosingDeclaration() {
+ int i = this.parentsPtr;
+ while (i > -1) {
+ ASTNode parent = parents[i];
+ if (parent instanceof AbstractMethodDeclaration) {
+ return parent;
+ } else if (parent instanceof Initializer) {
+ return parent;
+ } else if (parent instanceof FieldDeclaration) {
+ return parent;
+ } else if (parent instanceof TypeDeclaration) {
+ return parent;
+ }
+ i--;
+ }
+ return null;
+ }
+
+ public boolean visit(Block block, BlockScope blockScope) {
+ ASTNode enclosingDeclaration = getEnclosingDeclaration();
+ removeLocals(block.statements, enclosingDeclaration.sourceStart, block.sourceEnd);
+ pushParent(block);
+ return true;
+ }
+
+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope classScope) {
+ if (((constructorDeclaration.bits & ASTNode.IsDefaultConstructor) == 0) && !constructorDeclaration.isClinit()) {
+ removeLocals(
+ constructorDeclaration.arguments,
+ constructorDeclaration.declarationSourceStart,
+ constructorDeclaration.declarationSourceEnd);
+ removeLocals(
+ constructorDeclaration.statements,
+ constructorDeclaration.declarationSourceStart,
+ constructorDeclaration.declarationSourceEnd);
+ }
+ pushParent(constructorDeclaration);
+ return true;
+ }
+
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope methodScope) {
+ pushParent(fieldDeclaration);
+ return true;
+ }
+
+ public boolean visit(Initializer initializer, MethodScope methodScope) {
+ pushParent(initializer);
+ return true;
+ }
+
+ public boolean visit(MethodDeclaration methodDeclaration, Scope classScope) {
+ removeLocals(
+ methodDeclaration.arguments,
+ methodDeclaration.declarationSourceStart,
+ methodDeclaration.declarationSourceEnd);
+ removeLocals(
+ methodDeclaration.statements,
+ methodDeclaration.declarationSourceStart,
+ methodDeclaration.declarationSourceEnd);
+ pushParent(methodDeclaration);
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope blockScope) {
+ removeFields(localTypeDeclaration);
+ pushParent(localTypeDeclaration);
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
+ removeFields(memberTypeDeclaration);
+ pushParent(memberTypeDeclaration);
+ return true;
+ }
+
+ public void endVisit(Block block, BlockScope blockScope) {
+ popParent();
+ }
+
+ public void endVisit(Argument argument, BlockScope blockScope) {
+ endVisitRemoved(argument.declarationSourceStart, argument.sourceEnd);
+ }
+
+ public void endVisit(Argument argument, ClassScope classScope) {
+ endVisitRemoved(argument.declarationSourceStart, argument.sourceEnd);
+ }
+
+ public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope classScope) {
+ if (((constructorDeclaration.bits & ASTNode.IsDefaultConstructor) == 0) && !constructorDeclaration.isClinit()) {
+ endVisitPreserved(constructorDeclaration.bodyStart, constructorDeclaration.bodyEnd);
+ }
+ popParent();
+ }
+
+ public void endVisit(FieldDeclaration fieldDeclaration, MethodScope methodScope) {
+ endVisitRemoved(fieldDeclaration.declarationSourceStart, fieldDeclaration.sourceEnd);
+ endVisitPreserved(fieldDeclaration.sourceEnd, fieldDeclaration.declarationEnd);
+ popParent();
+ }
+
+ public void endVisit(Initializer initializer, MethodScope methodScope) {
+ endVisitPreserved(initializer.bodyStart, initializer.bodyEnd);
+ popParent();
+ }
+
+ public void endVisit(LocalDeclaration localDeclaration, BlockScope blockScope) {
+ endVisitRemoved(localDeclaration.declarationSourceStart, localDeclaration.sourceEnd);
+ }
+
+ public void endVisit(MethodDeclaration methodDeclaration, Scope classScope) {
+ endVisitPreserved(
+ methodDeclaration.bodyStart,
+ methodDeclaration.bodyEnd);
+ popParent();
+ }
+
+ public void endVisit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
+ endVisitRemoved(typeDeclaration.sourceStart, typeDeclaration.declarationSourceEnd);
+ popParent();
+ }
+
+ public void endVisit(TypeDeclaration typeDeclaration, ClassScope classScope) {
+ endVisitRemoved(typeDeclaration.sourceStart, typeDeclaration.declarationSourceEnd);
+ popParent();
+ }
+
+ private int indexOfFisrtNameAfter(int position) {
+ int left = 0;
+ int right = this.potentialVariableNamesPtr;
+
+ next : while (true) {
+ if (right < left) return -1;
+
+ int mid = left + (right - left) / 2;
+ int midPosition = this.potentialVariableNameStarts[mid];
+ if (midPosition < 0) {
+ int nextMid = indexOfNextName(mid);
+ if (nextMid < 0 || right < nextMid) { // no next index or next index is after 'right'
+ right = mid - 1;
+ continue next;
+ }
+ mid = nextMid;
+ midPosition = this.potentialVariableNameStarts[nextMid];
+
+ if (mid == right) { // mid and right are at the same index, we must move 'left'
+ int leftPosition = this.potentialVariableNameStarts[left];
+ if (leftPosition < 0 || leftPosition < position) { // 'left' is empty or 'left' is before the position
+ int nextLeft = indexOfNextName(left);
+ if (nextLeft < 0) return - 1;
+
+ left = nextLeft;
+ continue next;
+ }
+
+ return left;
+ }
+ }
+
+ if (left != right) {
+ if (midPosition < position) {
+ left = mid + 1;
+ } else {
+ right = mid;
+ }
+ } else {
+ if (midPosition < position) {
+ return -1;
+ }
+ return mid;
+ }
+ }
+ }
+
+ private int indexOfNextName(int index) {
+ int nextIndex = index + 1;
+ while (nextIndex <= this.potentialVariableNamesPtr &&
+ this.potentialVariableNames[nextIndex] == null) {
+ int jumpIndex = -this.potentialVariableNameStarts[nextIndex];
+ if (jumpIndex > 0) {
+ nextIndex = jumpIndex;
+ } else {
+ nextIndex++;
+ }
+ }
+
+ if (this.potentialVariableNamesPtr < nextIndex) {
+ if (index < this.potentialVariableNamesPtr) {
+ this.potentialVariableNamesPtr = index;
+ }
+ return -1;
+ }
+ if (index + 1 < nextIndex) {
+ this.potentialVariableNameStarts[index + 1] = -nextIndex;
+ }
+ return nextIndex;
+ }
+
+ private void removeNameAt(int index) {
+ this.potentialVariableNames[index] = null;
+ int nextIndex = indexOfNextName(index);
+ if (nextIndex != -1) {
+ this.potentialVariableNameStarts[index] = -nextIndex;
+ } else {
+ this.potentialVariableNamesPtr = index - 1;
+ }
+ }
+
+ private void endVisitPreserved(int start, int end) {
+ int i = indexOfFisrtNameAfter(start);
+ done : while (i != -1) {
+ int nameStart = this.potentialVariableNameStarts[i];
+ if (start < nameStart && nameStart < end) {
+ this.acceptName(this.potentialVariableNames[i]);
+ this.removeNameAt(i);
+ }
+
+ if (end < nameStart) break done;
+ i = indexOfNextName(i);
+ }
+ }
+
+ private void endVisitRemoved(int start, int end) {
+ int i = indexOfFisrtNameAfter(start);
+ done : while (i != -1) {
+ int nameStart = this.potentialVariableNameStarts[i];
+ if (start < nameStart && nameStart < end) {
+ this.removeNameAt(i);
+ }
+
+ if (end < nameStart) break done;
+ i = indexOfNextName(i);
+ }
+ }
+
+ private void removeLocals(Statement[] statements, int start, int end) {
+ if (statements != null) {
+ for (int i = 0; i < statements.length; i++) {
+ if (statements[i] instanceof LocalDeclaration) {
+ LocalDeclaration localDeclaration = (LocalDeclaration) statements[i];
+ int j = indexOfFisrtNameAfter(start);
+ done : while (j != -1) {
+ int nameStart = this.potentialVariableNameStarts[j];
+ if (start <= nameStart && nameStart <= end) {
+ if (CharOperation.equals(this.potentialVariableNames[j], localDeclaration.name, false)) {
+ this.removeNameAt(j);
+ }
+ }
+
+ if (end < nameStart) break done;
+ j = indexOfNextName(j);
+ }
+ }
+ }
+
+ }
+ }
+
+ private void removeFields(TypeDeclaration typeDeclaration) {
+ int start = typeDeclaration.declarationSourceStart;
+ int end = typeDeclaration.declarationSourceEnd;
+
+ FieldDeclaration[] fieldDeclarations = typeDeclaration.fields;
+ if (fieldDeclarations != null) {
+ for (int i = 0; i < fieldDeclarations.length; i++) {
+ int j = indexOfFisrtNameAfter(start);
+ done : while (j != -1) {
+ int nameStart = this.potentialVariableNameStarts[j];
+ if (start <= nameStart && nameStart <= end) {
+ if (CharOperation.equals(this.potentialVariableNames[j], fieldDeclarations[i].name, false)) {
+ this.removeNameAt(j);
+ }
+ }
+
+ if (end < nameStart) break done;
+ j = indexOfNextName(j);
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionJavadoc.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionJavadoc.java
new file mode 100644
index 0000000..0acd141
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionJavadoc.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+
+/**
+ * Node representing a Javadoc comment including code selection.
+ */
+public class CompletionJavadoc extends Javadoc {
+
+ Expression completionNode;
+
+ public CompletionJavadoc(int sourceStart, int sourceEnd) {
+ super(sourceStart, sourceEnd);
+ }
+
+ /**
+ * @return Returns the completionNode.
+ */
+ public Expression getCompletionNode() {
+ return this.completionNode;
+ }
+
+ /**
+ * Resolve selected node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws CompletionNodeFound
+ */
+ private void internalResolve(Scope scope) {
+ if (this.completionNode != null) {
+ if (this.completionNode instanceof CompletionOnJavadocTag) {
+ ((CompletionOnJavadocTag)this.completionNode).filterPossibleTags(scope);
+ } else {
+ boolean resolve = true;
+ if (this.completionNode instanceof CompletionOnJavadocParamNameReference) {
+ resolve = ((CompletionOnJavadocParamNameReference)this.completionNode).token != null;
+ }
+ if (resolve) {
+ switch (scope.kind) {
+ case Scope.CLASS_SCOPE:
+ this.completionNode.resolveType((ClassScope)scope);
+ break;
+ case Scope.METHOD_SCOPE:
+ this.completionNode.resolveType((MethodScope) scope);
+ break;
+ }
+ }
+ if (this.completionNode instanceof CompletionOnJavadocParamNameReference) {
+ CompletionOnJavadocParamNameReference paramNameReference = (CompletionOnJavadocParamNameReference) this.completionNode;
+ if (scope.kind == Scope.METHOD_SCOPE) {
+ paramNameReference.missingParams = missingParamTags(paramNameReference.binding, (MethodScope)scope);
+ }
+ }
+ }
+ Binding qualifiedBinding = null;
+ if (this.completionNode instanceof CompletionOnJavadocQualifiedTypeReference) {
+ CompletionOnJavadocQualifiedTypeReference typeRef = (CompletionOnJavadocQualifiedTypeReference) this.completionNode;
+ if (typeRef.packageBinding == null) {
+ qualifiedBinding = typeRef.resolvedType;
+ } else {
+ qualifiedBinding = typeRef.packageBinding;
+ }
+ } else if (this.completionNode instanceof CompletionOnJavadocMessageSend) {
+ CompletionOnJavadocMessageSend msg = (CompletionOnJavadocMessageSend) this.completionNode;
+ if (msg.receiver!=null && !msg.receiver.isThis()) qualifiedBinding = msg.receiver.resolvedType;
+ } else if (this.completionNode instanceof CompletionOnJavadocAllocationExpression) {
+ CompletionOnJavadocAllocationExpression alloc = (CompletionOnJavadocAllocationExpression) this.completionNode;
+ qualifiedBinding = alloc.type.resolvedType;
+ }
+ throw new CompletionNodeFound(this.completionNode, qualifiedBinding, scope);
+ }
+ }
+
+ /*
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
+ */
+ public StringBuffer print(int indent, StringBuffer output) {
+ printIndent(indent, output).append("/**\n"); //$NON-NLS-1$
+ boolean nodePrinted = false;
+ if (this.paramReferences != null) {
+ for (int i = 0, length = this.paramReferences.length; i < length; i++) {
+ printIndent(indent, output).append(" * @param "); //$NON-NLS-1$
+ this.paramReferences[i].print(indent, output).append('\n');
+ if (!nodePrinted && this.completionNode != null) {
+ nodePrinted = this.completionNode == this.paramReferences[i];
+ }
+ }
+ }
+ if (this.returnStatement != null) {
+ printIndent(indent, output).append(" * @"); //$NON-NLS-1$
+ this.returnStatement.print(indent, output).append('\n');
+ }
+ if (this.exceptionReferences != null) {
+ for (int i = 0, length = this.exceptionReferences.length; i < length; i++) {
+ printIndent(indent, output).append(" * @throws "); //$NON-NLS-1$
+ this.exceptionReferences[i].print(indent, output).append('\n');
+ if (!nodePrinted && this.completionNode != null) {
+ nodePrinted = this.completionNode == this.exceptionReferences[i];
+ }
+ }
+ }
+ if (this.seeReferences != null) {
+ for (int i = 0, length = this.seeReferences.length; i < length; i++) {
+ printIndent(indent, output).append(" * @see "); //$NON-NLS-1$
+ this.seeReferences[i].print(indent, output).append('\n');
+ if (!nodePrinted && this.completionNode != null) {
+ nodePrinted = this.completionNode == this.seeReferences[i];
+ }
+ }
+ }
+ if (!nodePrinted && this.completionNode != null) {
+ printIndent(indent, output).append(" * "); //$NON-NLS-1$
+ this.completionNode.print(indent, output).append('\n');
+ }
+ printIndent(indent, output).append(" */\n"); //$NON-NLS-1$
+ return output;
+ }
+
+ /**
+ * Resolve completion node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws CompletionNodeFound
+ */
+ public void resolve(ClassScope scope) {
+ super.resolve(scope);
+ internalResolve(scope);
+ }
+
+ /**
+ * Resolve completion node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws CompletionNodeFound
+ */
+ public void resolve(CompilationUnitScope scope) {
+ internalResolve(scope);
+ }
+
+ /**
+ * Resolve completion node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws CompletionNodeFound
+ */
+ public void resolve(MethodScope scope) {
+ super.resolve(scope);
+ internalResolve(scope);
+ }
+
+ /*
+ * Look for missing method @param tags
+ */
+ private char[][] missingParamTags(Binding paramNameRefBinding, MethodScope methScope) {
+
+ // Verify if there's some possible param tag
+ AbstractMethodDeclaration md = methScope.referenceMethod();
+ int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
+ if (md == null) return null;
+ int argumentsSize = md.arguments == null ? 0 : md.arguments.length;
+ if (argumentsSize == 0) return null;
+
+ // Store all method arguments if there's no @param in javadoc
+ if (paramTagsSize == 0) {
+ char[][] missingParams = new char[argumentsSize][];
+ for (int i = 0; i < argumentsSize; i++) {
+ missingParams[i] = md.arguments[i].name;
+ }
+ return missingParams;
+ }
+
+ // Look for missing arguments
+ char[][] missingParams = new char[argumentsSize][];
+ int size = 0;
+ for (int i = 0; i < argumentsSize; i++) {
+ Argument arg = md.arguments[i];
+ boolean found = false;
+ int paramNameRefCount = 0;
+ for (int j = 0; j < paramTagsSize && !found; j++) {
+ JavadocSingleNameReference param = this.paramReferences[j];
+ if (arg.binding == param.binding) {
+ if (param.binding == paramNameRefBinding) { // do not count first occurence of param name reference
+ paramNameRefCount++;
+ found = paramNameRefCount > 1;
+ } else {
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ missingParams[size++] = arg.name;
+ }
+ }
+ if (size > 0) {
+ if (size != argumentsSize) {
+ System.arraycopy(missingParams, 0, missingParams = new char[size][], 0, size);
+ }
+ return missingParams;
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionJavadocParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionJavadocParser.java
new file mode 100644
index 0000000..a49d75b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionJavadocParser.java
@@ -0,0 +1,850 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.codeassist.CompletionEngine;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArgumentExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocParser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.wst.jsdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Parser specialized for decoding javadoc comments which includes cursor location for code completion.
+ */
+public class CompletionJavadocParser extends JavadocParser {
+
+ // Initialize lengthes for block and inline tags tables
+ public final static int INLINE_ALL_TAGS_LENGTH;
+ public final static int BLOCK_ALL_TAGS_LENGTH;
+ static {
+ int length = 0;
+ for (int i=0; i');
+ }
+
+ public void resolve(BlockScope scope) {
+
+ super.resolve(scope);
+ throw new CompletionNodeFound(this, scope);
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java
new file mode 100644
index 0000000..01611c4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.BranchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+public class CompletionOnBrankStatementLabel extends BranchStatement {
+ public static final int BREAK = 1;
+ public static final int CONTINUE = 2;
+
+ private int kind;
+ public char[][] possibleLabels;
+
+ public CompletionOnBrankStatementLabel(int kind, char[] l, int s, int e, char[][] possibleLabels) {
+ super(l, s, e);
+ this.kind = kind;
+ this.possibleLabels = possibleLabels;
+ }
+
+ public FlowInfo analyseCode(BlockScope currentScope,
+ FlowContext flowContext, FlowInfo flowInfo) {
+ // Is never called
+ return null;
+ }
+
+ public void resolve(BlockScope scope) {
+ throw new CompletionNodeFound(this, scope);
+ }
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+ printIndent(indent, output);
+ if(kind == CONTINUE) {
+ output.append("continue "); //$NON-NLS-1$
+ } else {
+ output.append("break "); //$NON-NLS-1$
+ }
+ output.append(";"); //$NON-NLS-1$
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
new file mode 100644
index 0000000..548e34d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an access to the literal 'class' containing the cursor.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * String[].[cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ClassLiteralAccess;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnClassLiteralAccess extends ClassLiteralAccess {
+
+ public char[] completionIdentifier;
+ public int classStart;
+
+ public CompletionOnClassLiteralAccess(long pos, TypeReference t) {
+
+ super((int)pos, t);
+ this.classStart = (int) (pos >>> 32);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append("');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ if (super.resolveType(scope) == null)
+ throw new CompletionNodeFound();
+ else
+ throw new CompletionNodeFound(this, this.targetType, scope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
new file mode 100644
index 0000000..51dbdaa
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a explicit constructor call containing the cursor.
+ * e.g.
+ *
+ * class X {
+ * X() {
+ * this(1, 2, [cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * X() {
+ *
+ * }
+ * }
+ *
+ * The source range is always of length 0.
+ * The arguments of the constructor call are all the arguments defined
+ * before the cursor.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+
+public class CompletionOnExplicitConstructorCall extends ExplicitConstructorCall {
+
+ public CompletionOnExplicitConstructorCall(int accessMode) {
+ super(accessMode);
+ }
+
+ public StringBuffer printStatement(int tab, StringBuffer output) {
+
+ printIndent(tab, output);
+ output.append(" 0) output.append(", "); //$NON-NLS-1$
+ this.arguments[i].printExpression(0, output);
+ }
+ }
+ return output.append(")>;"); //$NON-NLS-1$
+ }
+
+ public void resolve(BlockScope scope) {
+
+ ReferenceBinding receiverType = scope.enclosingSourceType();
+
+ if (this.arguments != null) {
+ int argsLength = this.arguments.length;
+ for (int a = argsLength; --a >= 0;)
+ this.arguments[a].resolveType(scope);
+ }
+
+ if (this.accessMode != This && receiverType != null) {
+ if (receiverType.isHierarchyInconsistent())
+ throw new CompletionNodeFound();
+ receiverType = receiverType.superclass();
+ }
+ if (receiverType == null)
+ throw new CompletionNodeFound();
+ else
+ throw new CompletionNodeFound(this, receiverType, scope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnFieldName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnFieldName.java
new file mode 100644
index 0000000..1aa9040
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnFieldName.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+
+public class CompletionOnFieldName extends FieldDeclaration {
+ private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
+ public char[] realName;
+ public CompletionOnFieldName(char[] name, int sourceStart, int sourceEnd) {
+ super(CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd);
+ this.realName = name;
+ }
+
+ public StringBuffer printStatement(int tab, StringBuffer output) {
+
+ printIndent(tab, output).append(";"); //$NON-NLS-1$
+ }
+
+ public void resolve(MethodScope initializationScope) {
+ super.resolve(initializationScope);
+
+ throw new CompletionNodeFound(this, initializationScope);
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnFieldType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnFieldType.java
new file mode 100644
index 0000000..a16170f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnFieldType.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an type reference located as a potential return type for a class
+ * member, containing the cursor location.
+ * This node is only a fake-field wrapper of the actual completion node
+ * which is accessible as the fake-field type.
+ * e.g.
+ *
+ * class X {
+ * Obj[cursor]
+ * }
+ *
+ * ---> class X {
+ * ;
+ * }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+
+public class CompletionOnFieldType extends FieldDeclaration {
+ public boolean isLocalVariable;
+
+public CompletionOnFieldType(TypeReference type, boolean isLocalVariable){
+ super();
+ this.sourceStart = type.sourceStart;
+ this.sourceEnd = type.sourceEnd;
+ this.type = type;
+ this.name = CharOperation.NO_CHAR;
+ this.isLocalVariable = isLocalVariable;
+ if (type instanceof CompletionOnSingleTypeReference) {
+ ((CompletionOnSingleTypeReference) type).fieldTypeCompletionNode = this;
+ }
+}
+
+public StringBuffer printStatement(int tab, StringBuffer output) {
+ return type.print(tab, output).append(';');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnImportReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnImportReference.java
new file mode 100644
index 0000000..154a632
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnImportReference.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an import reference containing the cursor location.
+ * e.g.
+ *
+ * import java.io[cursor];
+ * class X {
+ * void foo() {
+ * }
+ * }
+ *
+ * --->
+ * class X {
+ * void foo() {
+ * }
+ * }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+
+public class CompletionOnImportReference extends ImportReference {
+
+public CompletionOnImportReference(char[][] tokens , long[] positions) {
+ super(tokens, positions, false);
+}
+public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
+
+ printIndent(indent, output).append(" 0) output.append('.');
+ output.append(tokens[i]);
+ }
+ return output.append('>');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadoc.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadoc.java
new file mode 100644
index 0000000..1db51f4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadoc.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+public interface CompletionOnJavadoc {
+
+ // Bit pattern for javadoc completion flags
+ int JAVADOC = 0x0001;
+ int EXCEPTION = 0x0002;
+ int TEXT = 0x0004;
+ int BASE_TYPES = 0x0008;
+ int ONLY_INLINE_TAG = 0x0010;
+ int REPLACE_TAG = 0x0020;
+ int FORMAL_REFERENCE = 0x0040;
+ int ALL_POSSIBLE_TAGS = 0x0080;
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags();
+
+ /**
+ * @param flags The completionFlags to add.
+ */
+ public void addCompletionFlags(int flags);
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocAllocationExpression.java
new file mode 100644
index 0000000..0f61509
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocAllocationExpression.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+
+public class CompletionOnJavadocAllocationExpression extends JavadocAllocationExpression implements CompletionOnJavadoc {
+ public int completionFlags = JAVADOC;
+ public int separatorPosition;
+
+ public CompletionOnJavadocAllocationExpression(JavadocAllocationExpression allocation, int position) {
+ super(allocation.sourceStart, allocation.sourceEnd);
+ this.arguments = allocation.arguments;
+ this.type = allocation.type;
+ this.tagValue = allocation.tagValue;
+ this.sourceEnd = allocation.sourceEnd;
+ this.separatorPosition = position;
+ this.qualification = allocation.qualification;
+ }
+
+ public CompletionOnJavadocAllocationExpression(JavadocAllocationExpression allocation, int position, int flags) {
+ this(allocation, position);
+ this.completionFlags |= flags;
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ public boolean completeAnException() {
+ return (this.completionFlags & EXCEPTION) != 0;
+ }
+
+ public boolean completeInText() {
+ return (this.completionFlags & TEXT) != 0;
+ }
+
+ public boolean completeBaseTypes() {
+ return (this.completionFlags & BASE_TYPES) != 0;
+ }
+
+ public boolean completeFormalReference() {
+ return (this.completionFlags & FORMAL_REFERENCE) != 0;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append(" 0) {
+ output.append('\n');
+ for (int i=0; i');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java
new file mode 100644
index 0000000..a63a114
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnJavadocFieldReference extends JavadocFieldReference implements CompletionOnJavadoc {
+// public boolean completionInText;
+ public int completionFlags = JAVADOC;
+ public int separatorPosition;
+
+ public CompletionOnJavadocFieldReference(Expression receiver, int tag, int position, int separatorPos, char[] name) {
+ super(null, (((long)position)<<32)+position-1);
+ this.receiver = receiver;
+ this.tagSourceStart = position;
+ this.tagSourceEnd = position;
+ this.tagValue = tag;
+ this.separatorPosition = separatorPos;
+ }
+
+ public CompletionOnJavadocFieldReference(JavadocFieldReference fieldRef, int position, char[] name) {
+ super(fieldRef.token, fieldRef.nameSourcePosition);
+ this.receiver = fieldRef.receiver;
+ this.separatorPosition = position;
+ this.tagSourceStart = fieldRef.tagSourceStart;
+ this.tagSourceEnd = fieldRef.tagSourceEnd;
+ this.tagValue = fieldRef.tagValue;
+ }
+
+ public CompletionOnJavadocFieldReference(JavadocMessageSend msgSend, int position) {
+ super(msgSend.selector, ((msgSend.nameSourcePosition>>32)<<32)+msgSend.sourceEnd);
+ this.receiver = msgSend.receiver;
+ this.separatorPosition = position;
+ this.tagSourceStart = msgSend.tagSourceStart;
+ this.tagSourceEnd = msgSend.tagSourceEnd;
+ this.tagValue = msgSend.tagValue;
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ public boolean completeAnException() {
+ return (this.completionFlags & EXCEPTION) != 0;
+ }
+
+ public boolean completeInText() {
+ return (this.completionFlags & TEXT) != 0;
+ }
+
+ public boolean completeBaseTypes() {
+ return (this.completionFlags & BASE_TYPES) != 0;
+ }
+
+ public boolean completeFormalReference() {
+ return (this.completionFlags & FORMAL_REFERENCE) != 0;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference#internalResolveType(org.eclipse.wst.jsdt.internal.compiler.lookup.Scope)
+ */
+ protected TypeBinding internalResolveType(Scope scope) {
+
+ if (this.token != null) {
+ return super.internalResolveType(scope);
+ }
+
+ // Resolve only receiver
+ if (this.receiver == null) {
+ this.receiverType = scope.enclosingSourceType();
+ } else if (scope.kind == Scope.CLASS_SCOPE) {
+ this.receiverType = this.receiver.resolveType((ClassScope) scope);
+ } else {
+ this.receiverType = this.receiver.resolveType((BlockScope)scope);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append(" 0) {
+ output.append('\n');
+ for (int i=0; i');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocMessageSend.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocMessageSend.java
new file mode 100644
index 0000000..a88bcd9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocMessageSend.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+
+public class CompletionOnJavadocMessageSend extends JavadocMessageSend implements CompletionOnJavadoc {
+ public int completionFlags = JAVADOC;
+ public int separatorPosition;
+
+ public CompletionOnJavadocMessageSend(JavadocMessageSend method, int position) {
+ super(method.selector, method.nameSourcePosition);
+ this.arguments = method.arguments;
+ this.receiver = method.receiver;
+ this.sourceEnd = method.sourceEnd;
+ this.tagValue = method.tagValue;
+ this.separatorPosition = position;
+ }
+
+ public CompletionOnJavadocMessageSend(JavadocMessageSend method, int position, int flags) {
+ this(method, position);
+ this.completionFlags |= flags;
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ public boolean completeAnException() {
+ return (this.completionFlags & EXCEPTION) != 0;
+ }
+
+ public boolean completeInText() {
+ return (this.completionFlags & TEXT) != 0;
+ }
+
+ public boolean completeBaseTypes() {
+ return (this.completionFlags & BASE_TYPES) != 0;
+ }
+
+ public boolean completeFormalReference() {
+ return (this.completionFlags & FORMAL_REFERENCE) != 0;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append(" 0) {
+ output.append('\n');
+ for (int i=0; i');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java
new file mode 100644
index 0000000..f107b69
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnJavadocParamNameReference extends JavadocSingleNameReference implements CompletionOnJavadoc {
+ public int completionFlags = JAVADOC;
+ public char[][] missingParams;
+
+ public CompletionOnJavadocParamNameReference(char[] name, long pos, int start, int end) {
+ super(name, pos, start, end);
+ }
+
+ public CompletionOnJavadocParamNameReference(JavadocSingleNameReference nameRef) {
+ super(nameRef.token, (((long)nameRef.sourceStart)<<32)+nameRef.sourceEnd, nameRef.tagSourceStart, nameRef.tagSourceStart);
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append("');
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference#reportError(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope)
+ */
+ public TypeBinding reportError(BlockScope scope) {
+ return null;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocQualifiedTypeReference.java
new file mode 100644
index 0000000..b736dff
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocQualifiedTypeReference.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+
+public class CompletionOnJavadocQualifiedTypeReference extends JavadocQualifiedTypeReference implements CompletionOnJavadoc {
+ public int completionFlags = JAVADOC;
+ public char[] completionIdentifier;
+
+ public CompletionOnJavadocQualifiedTypeReference(char[][] sources, char[] identifier, long[] pos, int tagStart, int tagEnd) {
+ super(sources, pos, tagStart, tagEnd);
+ this.completionIdentifier = identifier;
+ }
+
+ public CompletionOnJavadocQualifiedTypeReference(JavadocQualifiedTypeReference typeRef) {
+ super(typeRef.tokens, typeRef.sourcePositions, typeRef.tagSourceStart, typeRef.tagSourceStart);
+ this.completionIdentifier = CharOperation.NO_CHAR;
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ public boolean completeAnException() {
+ return (this.completionFlags & EXCEPTION) != 0;
+ }
+
+ public boolean completeInText() {
+ return (this.completionFlags & TEXT) != 0;
+ }
+
+ public boolean completeBaseTypes() {
+ return (this.completionFlags & BASE_TYPES) != 0;
+ }
+
+ public boolean completeFormalReference() {
+ return (this.completionFlags & FORMAL_REFERENCE) != 0;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append(" 0) {
+ output.append('\n');
+ for (int i=0; i');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocSingleTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocSingleTypeReference.java
new file mode 100644
index 0000000..6add1e8
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocSingleTypeReference.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+
+public class CompletionOnJavadocSingleTypeReference extends JavadocSingleTypeReference implements CompletionOnJavadoc {
+ public int completionFlags = JAVADOC;
+
+ public CompletionOnJavadocSingleTypeReference(char[] source, long pos, int tagStart, int tagEnd) {
+ super(source, pos, tagStart, tagEnd);
+ }
+
+ public CompletionOnJavadocSingleTypeReference(JavadocSingleTypeReference typeRef) {
+ super(typeRef.token, (((long)typeRef.sourceStart)<<32)+typeRef.sourceEnd, typeRef.tagSourceStart, typeRef.tagSourceStart);
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ public boolean completeAnException() {
+ return (this.completionFlags & EXCEPTION) != 0;
+ }
+
+ public boolean completeInText() {
+ return (this.completionFlags & TEXT) != 0;
+ }
+
+ public boolean completeBaseTypes() {
+ return (this.completionFlags & BASE_TYPES) != 0;
+ }
+
+ public boolean completeFormalReference() {
+ return (this.completionFlags & FORMAL_REFERENCE) != 0;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append(" 0) {
+ output.append('\n');
+ for (int i=0; i');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocTag.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocTag.java
new file mode 100644
index 0000000..92fd1f9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnJavadocTag.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocTagConstants;
+
+public class CompletionOnJavadocTag extends JavadocSingleNameReference implements JavadocTagConstants, CompletionOnJavadoc {
+ public int completionFlags = JAVADOC;
+ public final static char[][][] NO_CHAR_CHAR_CHAR = new char[0][][];
+ private char[][][] possibleTags = NO_CHAR_CHAR_CHAR;
+
+ public CompletionOnJavadocTag(char[] source, long pos, int tagStart, int tagEnd, char[][][] possibleTags, boolean orphan) {
+ super(source, pos, tagStart, tagEnd);
+ this.possibleTags = possibleTags;
+ if (orphan) this.completionFlags |= ALL_POSSIBLE_TAGS;
+ }
+
+ /**
+ * @param flags The completionFlags to set.
+ */
+ public void addCompletionFlags(int flags) {
+ this.completionFlags |= flags;
+ }
+
+ /**
+ * Get completion node flags.
+ *
+ * @return int Flags of the javadoc completion node.
+ */
+ public int getCompletionFlags() {
+ return this.completionFlags;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression#printExpression(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append(" 0) {
+ output.append("\npossible block tags:"); //$NON-NLS-1$
+ for (int i=0; i 0) {
+ output.append("\npossible inline tags:"); //$NON-NLS-1$
+ for (int i=0; i');
+ }
+
+ public void filterPossibleTags(Scope scope) {
+ if (this.possibleTags == null || this.possibleTags.length == 0 || (this.completionFlags & ALL_POSSIBLE_TAGS) != 0) {
+ return;
+ }
+ int kind = scope.kind;
+ char[][] specifiedTags = null;
+ switch (kind) {
+ case Scope.COMPILATION_UNIT_SCOPE:
+ case Scope.CLASS_SCOPE:
+ specifiedTags = CLASS_TAGS;
+ break;
+ case Scope.METHOD_SCOPE:
+ MethodScope methodScope = (MethodScope) scope;
+ if (methodScope.referenceMethod() == null) {
+ if (methodScope.initializedField == null) {
+ specifiedTags = PACKAGE_TAGS;
+ } else {
+ specifiedTags = FIELD_TAGS;
+ }
+ } else {
+ specifiedTags = METHOD_TAGS;
+ }
+ break;
+ default:
+ return;
+ }
+ int kinds = this.possibleTags.length;
+ for (int k=0; k= ClassFileConstants.JDK1_5) {
+// if (((ClassScope)scope).referenceContext.binding.isGenericType()) {
+// filteredTags[size++] = possibleTag;
+// }
+ }
+ break;
+ case Scope.COMPILATION_UNIT_SCOPE:
+ if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
+ filteredTags[size++] = possibleTag;
+ }
+ break;
+ default:
+ filteredTags[size++] = possibleTag;
+ break;
+ }
+ } else {
+ filteredTags[size++] = possibleTag;
+ }
+ break;
+ }
+ }
+ }
+ if (size'); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnKeyword2.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnKeyword2.java
new file mode 100644
index 0000000..1f889fc
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnKeyword2.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+
+public class CompletionOnKeyword2 extends ImportReference implements CompletionOnKeyword {
+ private char[] token;
+ private char[][] possibleKeywords;
+ public CompletionOnKeyword2(char[] token, long pos, char[][] possibleKeywords) {
+ super(new char[][]{token}, new long[]{pos}, false);
+ this.token = token;
+ this.possibleKeywords = possibleKeywords;
+ }
+ public boolean canCompleteEmptyToken() {
+ return false;
+ }
+ public char[] getToken() {
+ return token;
+ }
+ public char[][] getPossibleKeywords() {
+ return possibleKeywords;
+ }
+ public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
+
+ return printIndent(indent, output).append("'); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnKeyword3.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnKeyword3.java
new file mode 100644
index 0000000..2ffa891
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnKeyword3.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnKeyword3 extends SingleNameReference implements CompletionOnKeyword{
+ private char[][] possibleKeywords;
+ public CompletionOnKeyword3(char[] token, long pos, char[] possibleKeyword) {
+ this(token, pos, new char[][]{possibleKeyword});
+ }
+ public CompletionOnKeyword3(char[] token, long pos, char[][] possibleKeywords) {
+ super(token, pos);
+ this.token = token;
+ this.possibleKeywords = possibleKeywords;
+ }
+ public boolean canCompleteEmptyToken() {
+ return false;
+ }
+ public char[] getToken() {
+ return token;
+ }
+ public char[][] getPossibleKeywords() {
+ return possibleKeywords;
+ }
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ return output.append("'); //$NON-NLS-1$
+ }
+ public TypeBinding resolveType(BlockScope scope) {
+ throw new CompletionNodeFound(this, scope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnLocalName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnLocalName.java
new file mode 100644
index 0000000..0a3816d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnLocalName.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+
+public class CompletionOnLocalName extends LocalDeclaration {
+ private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
+ public char[] realName;
+
+ public CompletionOnLocalName(char[] name, int sourceStart, int sourceEnd){
+
+ super(CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd);
+ this.realName = name;
+ }
+
+ public void resolve(BlockScope scope) {
+
+ super.resolve(scope);
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ public StringBuffer printAsExpression(int indent, StringBuffer output) {
+ printIndent(indent, output);
+ output.append("');
+ }
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+ this.printAsExpression(indent, output);
+ return output.append(';');
+ }
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java
new file mode 100644
index 0000000..17cf18c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMemberAccess.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an access to a member (field reference or message send)
+ * containing the completion identifier.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * bar().fred[cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemMethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnMemberAccess extends FieldReference {
+
+ public boolean isInsideAnnotation;
+ public boolean isStatic;
+
+ public CompletionOnMemberAccess(char[] source, long pos, boolean isInsideAnnotation) {
+
+ super(source, pos);
+ this.isInsideAnnotation = isInsideAnnotation;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append("');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ this.receiverType = receiver.resolveType(scope);
+ if (scope.getJavaLangFunction().equals(this.receiverType))
+ {
+ Binding typeBinding = receiver.alternateBinding();
+ if (typeBinding instanceof TypeBinding)
+ {
+ this.receiverType=(TypeBinding)typeBinding;
+ isStatic=true;
+ }
+ }
+ if ((receiver.bits&Binding.TYPE)!=0)
+ isStatic=true;
+ if(this.receiverType != null && this.receiverType.isAnonymousType())
+ isStatic=false;
+
+ if (this.receiverType == null && receiver instanceof MessageSend) {
+ MessageSend messageSend = (MessageSend) receiver;
+ if(messageSend.receiver instanceof ThisReference) {
+ Expression[] arguments = messageSend.arguments;
+ int length = arguments == null ? 0 : arguments.length;
+ TypeBinding[] argBindings = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ argBindings[i] = arguments[i].resolvedType;
+ if(argBindings[i] == null || !argBindings[i].isValidBinding()) {
+ throw new CompletionNodeFound();
+ }
+ }
+
+ ProblemMethodBinding problemMethodBinding = new ProblemMethodBinding(messageSend.selector, argBindings, ProblemReasons.NotFound);
+ throw new CompletionNodeFound(this, problemMethodBinding, scope);
+ }
+ }
+
+ if (this.receiverType == null || this.receiverType.isBaseType())
+ throw new CompletionNodeFound(this, scope);
+ else
+ throw new CompletionNodeFound(this, this.receiverType, scope);
+ // array types are passed along to find the length field
+ }
+
+ public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) {
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ /**
+ *
+ * @return true
because this node is special because it is a completion node
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#isSpecialNode()
+ */
+ public boolean isSpecialNode() {
+ return true;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMessageSend.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMessageSend.java
new file mode 100644
index 0000000..0bbee91
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMessageSend.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a message send containing the cursor.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * this.bar(1, 2, [cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ * The source range is always of length 0.
+ * The arguments of the message send are all the arguments defined
+ * before the cursor.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnMessageSend extends MessageSend {
+
+ public TypeBinding resolveType(BlockScope scope) {
+ if (arguments != null) {
+ int argsLength = arguments.length;
+ for (int a = argsLength; --a >= 0;)
+ arguments[a].resolveType(scope);
+ }
+
+ if (receiver==null || receiver.isImplicitThis())
+ throw new CompletionNodeFound(this, null, scope);
+
+ this.actualReceiverType = receiver.resolveType(scope);
+ if (this.actualReceiverType == null || this.actualReceiverType.isBaseType())
+ throw new CompletionNodeFound();
+
+ if (this.actualReceiverType.isArrayType())
+ this.actualReceiverType = scope.getJavaLangObject();
+ throw new CompletionNodeFound(this, this.actualReceiverType, scope);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append(" 0) output.append(", "); //$NON-NLS-1$
+ arguments[i].printExpression(0, output);
+ }
+ }
+ return output.append(")>"); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMessageSendName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMessageSendName.java
new file mode 100644
index 0000000..2b0be38
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMessageSendName.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnMessageSendName extends MessageSend {
+ public CompletionOnMessageSendName(char[] selector, int start, int end) {
+ super();
+ this.selector = selector;
+ this.sourceStart = start;
+ this.sourceEnd = end;
+ this.nameSourcePosition = end;
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ if (receiver==null || receiver.isImplicitThis())
+ throw new CompletionNodeFound();
+
+ this.actualReceiverType = receiver.resolveType(scope);
+ if (this.actualReceiverType == null || this.actualReceiverType.isBaseType() || this.actualReceiverType.isArrayType())
+ throw new CompletionNodeFound();
+
+ if(this.receiver instanceof NameReference) {
+ throw new CompletionNodeFound(this, ((NameReference)this.receiver).binding, scope);
+ } else if(this.receiver instanceof MessageSend) {
+ throw new CompletionNodeFound(this, ((MessageSend)this.receiver).binding, scope);
+ }
+ throw new CompletionNodeFound(this, this.actualReceiverType, scope);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append(""); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMethodName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMethodName.java
new file mode 100644
index 0000000..1150b17
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnMethodName.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+
+public class CompletionOnMethodName extends MethodDeclaration {
+ public int selectorEnd;
+
+ public CompletionOnMethodName(CompilationResult compilationResult){
+ super(compilationResult);
+ }
+
+ public StringBuffer print(int indent, StringBuffer output) {
+
+ printIndent(indent, output);
+ output.append(" 0) output.append(", "); //$NON-NLS-1$
+ arguments[i].print(0, output);
+ }
+ }
+ output.append(')');
+ return output.append('>');
+ }
+
+ public void resolve(ClassScope upperScope) {
+
+ super.resolve(upperScope);
+ throw new CompletionNodeFound(this, upperScope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
new file mode 100644
index 0000000..cd6576d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an allocation expression containing the cursor.
+ * If the allocation expression is not qualified, the enclosingInstance field
+ * is null.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * new Bar(1, 2, [cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnQualifiedAllocationExpression extends QualifiedAllocationExpression {
+public TypeBinding resolveType(BlockScope scope) {
+ if (arguments != null) {
+ int argsLength = arguments.length;
+ for (int a = argsLength; --a >= 0;)
+ arguments[a].resolveType(scope);
+ }
+
+ if (enclosingInstance != null) {
+ TypeBinding enclosingType = enclosingInstance.resolveType(scope);
+ if (enclosingType == null || !(enclosingType instanceof ReferenceBinding)) {
+ throw new CompletionNodeFound();
+ }
+ this.resolvedType = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingType);
+ if (!(this.resolvedType instanceof ReferenceBinding))
+ throw new CompletionNodeFound(); // no need to continue if its an array or base type
+ } else {
+ this.resolvedType = type.resolveType(scope, true /* check bounds*/);
+ if (!(this.resolvedType instanceof ReferenceBinding))
+ throw new CompletionNodeFound(); // no need to continue if its an array or base type
+ }
+
+ throw new CompletionNodeFound(this, this.resolvedType, scope);
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+ if (this.enclosingInstance == null)
+ output.append("');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java
new file mode 100644
index 0000000..984700b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a qualified name reference containing the completion identifier.
+ * e.g.
+ *
+ * class X {
+ * Y y;
+ * void foo() {
+ * y.fred.ba[cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * Y y;
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnQualifiedNameReference extends QualifiedNameReference {
+ public char[] completionIdentifier;
+ public boolean isInsideAnnotationAttribute;
+public CompletionOnQualifiedNameReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions, boolean isInsideAnnotationAttribute) {
+ super(previousIdentifiers, positions, (int) (positions[0] >>> 32), (int) positions[positions.length - 1]);
+ this.completionIdentifier = completionIdentifier;
+ this.isInsideAnnotationAttribute = isInsideAnnotationAttribute;
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append("');
+ return output;
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // it can be a package, type, member type, local variable or field
+ binding = scope.getBinding(tokens, this);
+ if (!binding.isValidBinding()) {
+ if (binding instanceof ProblemFieldBinding) {
+ scope.problemReporter().invalidField(this, (FieldBinding) binding);
+ } else if (binding instanceof ProblemReferenceBinding) {
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ } else {
+ scope.problemReporter().unresolvableReference(this, binding);
+ }
+
+ if (binding.problemId() == ProblemReasons.NotFound) {
+ throw new CompletionNodeFound(this, binding, scope);
+ }
+
+ throw new CompletionNodeFound();
+ }
+
+ throw new CompletionNodeFound(this, binding, scope);
+}
+
+
+public boolean isSpecialNode()
+{
+ return true;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedType.java
new file mode 100644
index 0000000..fbdd942
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedType.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnQualifiedType extends
+QualifiedNameReference {
+
+
+ public char[] completionIdentifier;
+public CompletionOnQualifiedType(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+ super(previousIdentifiers, positions, (int) (positions[0] >>> 32), (int) positions[positions.length - 1]);
+ this.completionIdentifier = completionIdentifier;
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append("');
+ return output;
+}
+
+public TypeBinding resolveType(BlockScope scope) {
+ // it can be a package, type, member type, local variable or field
+ binding = scope.getBinding(tokens, this);
+ if (!binding.isValidBinding()) {
+ if (binding instanceof ProblemFieldBinding) {
+ scope.problemReporter().invalidField(this, (FieldBinding) binding);
+ } else if (binding instanceof ProblemReferenceBinding) {
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ } else {
+ scope.problemReporter().unresolvableReference(this, binding);
+ }
+
+ if (binding.problemId() == ProblemReasons.NotFound) {
+ throw new CompletionNodeFound(this, binding, scope);
+ }
+
+ throw new CompletionNodeFound();
+ }
+
+ throw new CompletionNodeFound(this, binding, scope);
+}
+
+
+public boolean isSpecialNode()
+{
+ return true;
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
new file mode 100644
index 0000000..c6f5ada
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as part
+ * of a qualified name.
+ * e.g.
+ *
+ * class X extends java.lang.Obj[cursor]
+ *
+ * ---> class X extends
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnQualifiedTypeReference extends QualifiedTypeReference {
+ public static final int K_TYPE = 0;
+ public static final int K_CLASS = 1;
+ public static final int K_INTERFACE = 2;
+ public static final int K_EXCEPTION = 3;
+
+ private int kind = K_TYPE;
+ public char[] completionIdentifier;
+public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+ this(previousIdentifiers, completionIdentifier, positions, K_TYPE);
+}
+public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions, int kind) {
+ super(previousIdentifiers, positions);
+ this.completionIdentifier = completionIdentifier;
+ this.kind = kind;
+}
+public void aboutToResolve(Scope scope) {
+ getTypeBinding(scope);
+}
+/*
+ * No expansion of the completion reference into an array one
+ */
+public TypeReference copyDims(int dim){
+ return this;
+}
+protected TypeBinding getTypeBinding(Scope scope) {
+ // it can be a package, type or member type
+ Binding binding = scope.parent.getTypeOrPackage(tokens); // step up from the ClassScope
+ if (!binding.isValidBinding()) {
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ throw new CompletionNodeFound();
+ }
+
+ throw new CompletionNodeFound(this, binding, scope);
+}
+public boolean isClass(){
+ return this.kind == K_CLASS;
+}
+
+public boolean isInterface(){
+ return this.kind == K_INTERFACE;
+}
+
+public boolean isException(){
+ return this.kind == K_EXCEPTION;
+}
+public boolean isSuperType(){
+ return this.kind == K_CLASS || this.kind == K_INTERFACE;
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+ switch (this.kind) {
+ case K_CLASS :
+ output.append("');
+ return output;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleNameReference.java
new file mode 100644
index 0000000..af47294
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleNameReference.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a single name reference containing the completion identifier.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * ba[cursor]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnSingleNameReference extends SingleNameReference {
+
+ public char[][] possibleKeywords;
+ public boolean canBeExplicitConstructor;
+ public boolean isInsideAnnotationAttribute;
+
+ public CompletionOnSingleNameReference(char[] source, long pos, boolean isInsideAnnotationAttribute) {
+ this(source, pos, null, false, isInsideAnnotationAttribute);
+ }
+
+ public CompletionOnSingleNameReference(char[] source, long pos, char[][] possibleKeywords, boolean canBeExplicitConstructor, boolean isInsideAnnotationAttribute) {
+ super(source, (pos>=0)?pos : 0);
+ this.possibleKeywords = possibleKeywords;
+ this.canBeExplicitConstructor = canBeExplicitConstructor;
+ this.isInsideAnnotationAttribute = isInsideAnnotationAttribute;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append("');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ if(scope instanceof MethodScope) {
+ throw new CompletionNodeFound(this, scope, false);
+ }
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) {
+ throw new CompletionNodeFound(this, scope);
+ }
+ public boolean isSpecialNode()
+ {
+ return true;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeName.java
new file mode 100644
index 0000000..c906006
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeName.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnSingleTypeName extends SingleNameReference {
+
+ public CompletionOnSingleTypeName(char[] source, long pos) {
+ super(source, pos);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append("');
+ }
+ public void aboutToResolve(Scope scope) {
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ public boolean isSpecialNode()
+ {
+ return true;
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location)
+ {
+ throw new CompletionNodeFound(this, scope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
new file mode 100644
index 0000000..e8d7eb5
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as a single
+ * name reference.
+ * e.g.
+ *
+ * class X extends Obj[cursor]
+ *
+ * ---> class X extends
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompletionOnSingleTypeReference extends SingleTypeReference {
+ public static final int K_TYPE = 0;
+ public static final int K_CLASS = 1;
+ public static final int K_INTERFACE = 2;
+ public static final int K_EXCEPTION = 3;
+
+ private int kind = K_TYPE;
+ public boolean isCompletionNode;
+ public boolean isConstructorType;
+ public CompletionOnFieldType fieldTypeCompletionNode;
+
+ public CompletionOnSingleTypeReference(char[] source, long pos) {
+ this(source, pos, K_TYPE);
+ }
+ public CompletionOnSingleTypeReference(char[] source, long pos, int kind) {
+ super(source, pos);
+ isCompletionNode = true;
+ this.kind = kind;
+ }
+ public void aboutToResolve(Scope scope) {
+ getTypeBinding(scope);
+ }
+ /*
+ * No expansion of the completion reference into an array one
+ */
+ public TypeReference copyDims(int dim){
+ return this;
+ }
+ protected TypeBinding getTypeBinding(Scope scope) {
+ if (this.fieldTypeCompletionNode != null) {
+ throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope);
+ }
+ if(isCompletionNode) {
+ throw new CompletionNodeFound(this, scope);
+ } else {
+ return super.getTypeBinding(scope);
+ }
+ }
+ public boolean isClass(){
+ return this.kind == K_CLASS;
+ }
+ public boolean isInterface(){
+ return this.kind == K_INTERFACE;
+ }
+ public boolean isException(){
+ return this.kind == K_EXCEPTION;
+ }
+ public boolean isSuperType(){
+ return this.kind == K_CLASS || this.kind == K_INTERFACE;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output){
+ switch (this.kind) {
+ case K_CLASS :
+ output.append("');
+ }
+
+ public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+ if (this.fieldTypeCompletionNode != null) {
+ throw new CompletionNodeFound(this.fieldTypeCompletionNode, scope);
+ }
+ if(isCompletionNode) {
+ throw new CompletionNodeFound(this, enclosingType, scope);
+ } else {
+ return super.resolveTypeEnclosing(scope, enclosingType);
+ }
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolve(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope)
+ */
+ public void resolve(BlockScope scope) {
+ super.resolve(scope);
+
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference#resolveType(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, boolean)
+ */
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+ super.resolveType(scope, checkBounds);
+
+ throw new CompletionNodeFound(this, scope);
+ }
+
+ /**
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolveForAllocation(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode)
+ */
+ public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) {
+ return this.resolveType(scope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnStringLiteral.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnStringLiteral.java
new file mode 100644
index 0000000..552648a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionOnStringLiteral.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a string literal.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * String s = "a[cursor]"
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ * String s =
+ * }
+ * }
+ */
+
+public class CompletionOnStringLiteral extends StringLiteral {
+ public int contentStart;
+ public int contentEnd;
+ public CompletionOnStringLiteral(char[] token, int s, int e, int cs, int ce, int lineNumber) {
+ super(token, s, e, lineNumber);
+ this.contentStart = cs;
+ this.contentEnd = ce;
+ }
+
+ public CompletionOnStringLiteral(int s, int e, int cs, int ce) {
+ super(s,e);
+ this.contentStart = cs;
+ this.contentEnd = ce;
+ }
+ public TypeBinding resolveType(ClassScope scope) {
+ throw new CompletionNodeFound(this, null, scope);
+ }
+ public TypeBinding resolveType(BlockScope scope) {
+ throw new CompletionNodeFound(this, null, scope);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append("');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java
new file mode 100644
index 0000000..c6a61e4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionParser.java
@@ -0,0 +1,3323 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ * -1 means completion at the very beginning of the source
+ * 0 means completion behind the first character
+ * n means completion behind the n-th character
+ */
+
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.core.ast.IFieldReference;
+import org.eclipse.wst.jsdt.core.ast.ISingleNameReference;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.Keywords;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Statement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocParser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredBlock;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredElement;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredField;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredLocalVariable;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredMethod;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredType;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+public class CompletionParser extends AssistParser {
+ // OWNER
+ protected static final int COMPLETION_PARSER = 1024;
+ protected static final int COMPLETION_OR_ASSIST_PARSER = ASSIST_PARSER + COMPLETION_PARSER;
+
+ // KIND : all values known by CompletionParser are between 1025 and 1549
+ protected static final int K_BLOCK_DELIMITER = COMPLETION_PARSER + 1; // whether we are inside a block
+ protected static final int K_SELECTOR_INVOCATION_TYPE = COMPLETION_PARSER + 2; // whether we are inside a message send
+ protected static final int K_SELECTOR_QUALIFIER = COMPLETION_PARSER + 3; // whether we are inside a message send
+ protected static final int K_BETWEEN_CATCH_AND_RIGHT_PAREN = COMPLETION_PARSER + 4; // whether we are between the keyword 'catch' and the following ')'
+ protected static final int K_NEXT_TYPEREF_IS_CLASS = COMPLETION_PARSER + 5; // whether the next type reference is a class
+ protected static final int K_NEXT_TYPEREF_IS_INTERFACE = COMPLETION_PARSER + 6; // whether the next type reference is an interface
+ protected static final int K_NEXT_TYPEREF_IS_EXCEPTION = COMPLETION_PARSER + 7; // whether the next type reference is an exception
+ protected static final int K_BETWEEN_NEW_AND_LEFT_BRACKET = COMPLETION_PARSER + 8; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
+ protected static final int K_INSIDE_THROW_STATEMENT = COMPLETION_PARSER + 9; // whether we are between the keyword 'throw' and the end of a throw statement
+ protected static final int K_INSIDE_RETURN_STATEMENT = COMPLETION_PARSER + 10; // whether we are between the keyword 'return' and the end of a return statement
+ protected static final int K_CAST_STATEMENT = COMPLETION_PARSER + 11; // whether we are between ')' and the end of a cast statement
+ protected static final int K_LOCAL_INITIALIZER_DELIMITER = COMPLETION_PARSER + 12;
+ protected static final int K_ARRAY_INITIALIZER = COMPLETION_PARSER + 13;
+ protected static final int K_ARRAY_CREATION = COMPLETION_PARSER + 14;
+ protected static final int K_UNARY_OPERATOR = COMPLETION_PARSER + 15;
+ protected static final int K_BINARY_OPERATOR = COMPLETION_PARSER + 16;
+ protected static final int K_ASSISGNMENT_OPERATOR = COMPLETION_PARSER + 17;
+ protected static final int K_CONDITIONAL_OPERATOR = COMPLETION_PARSER + 18;
+ protected static final int K_BETWEEN_IF_AND_RIGHT_PAREN = COMPLETION_PARSER + 19;
+ protected static final int K_BETWEEN_WHILE_AND_RIGHT_PAREN = COMPLETION_PARSER + 20;
+ protected static final int K_BETWEEN_FOR_AND_RIGHT_PAREN = COMPLETION_PARSER + 21;
+ protected static final int K_BETWEEN_SWITCH_AND_RIGHT_PAREN = COMPLETION_PARSER + 22;
+ protected static final int K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN = COMPLETION_PARSER + 23;
+ protected static final int K_INSIDE_ASSERT_STATEMENT = COMPLETION_PARSER + 24;
+ protected static final int K_SWITCH_LABEL= COMPLETION_PARSER + 25;
+ protected static final int K_BETWEEN_CASE_AND_COLON = COMPLETION_PARSER + 26;
+ protected static final int K_BETWEEN_DEFAULT_AND_COLON = COMPLETION_PARSER + 27;
+ protected static final int K_BETWEEN_LEFT_AND_RIGHT_BRACKET = COMPLETION_PARSER + 28;
+ protected static final int K_EXTENDS_KEYWORD = COMPLETION_PARSER + 29;
+ protected static final int K_PARAMETERIZED_METHOD_INVOCATION = COMPLETION_PARSER + 30;
+ protected static final int K_PARAMETERIZED_ALLOCATION = COMPLETION_PARSER + 31;
+ protected static final int K_PARAMETERIZED_CAST = COMPLETION_PARSER + 32;
+ protected static final int K_BETWEEN_ANNOTATION_NAME_AND_RPAREN = COMPLETION_PARSER + 33;
+ protected static final int K_INSIDE_BREAK_STATEMENT = COMPLETION_PARSER + 34;
+ protected static final int K_INSIDE_CONTINUE_STATEMENT = COMPLETION_PARSER + 35;
+ protected static final int K_LABEL = COMPLETION_PARSER + 36;
+ protected static final int K_MEMBER_VALUE_ARRAY_INITIALIZER = COMPLETION_PARSER + 37;
+
+ public final static char[] FAKE_TYPE_NAME = new char[]{' '};
+ public final static char[] FAKE_METHOD_NAME = new char[]{' '};
+ public final static char[] FAKE_ARGUMENT_NAME = new char[]{' '};
+ public final static char[] VALUE = new char[]{'v', 'a', 'l', 'u', 'e'};
+
+ /* public fields */
+
+ public int cursorLocation;
+ public ASTNode assistNodeParent; // the parent node of assist node
+ /* the following fields are internal flags */
+
+ // block kind
+ static final int IF = 1;
+ static final int TRY = 2;
+ static final int CATCH = 3;
+ static final int WHILE = 4;
+ static final int SWITCH = 5;
+ static final int FOR = 6;
+ static final int DO = 7;
+ static final int SYNCHRONIZED = 8;
+
+ // label kind
+ static final int DEFAULT = 1;
+
+ // invocation type constants
+ static final int EXPLICIT_RECEIVER = 0;
+ static final int NO_RECEIVER = -1;
+ static final int SUPER_RECEIVER = -2;
+ static final int NAME_RECEIVER = -3;
+ static final int ALLOCATION = -4;
+ static final int QUALIFIED_ALLOCATION = -5;
+
+ static final int QUESTION = 1;
+ static final int COLON = 2;
+
+ // K_BETWEEN_ANNOTATION_NAME_AND_RPAREN arguments
+ static final int LPAREN_NOT_CONSUMED = 1;
+ static final int LPAREN_CONSUMED = 2;
+ static final int ANNOTATION_NAME_COMPLETION = 4;
+
+ // K_PARAMETERIZED_METHOD_INVOCATION arguments
+ static final int INSIDE_NAME = 1;
+
+ // the type of the current invocation (one of the invocation type constants)
+ int invocationType;
+
+ // a pointer in the expression stack to the qualifier of a invocation
+ int qualifier;
+
+ // last modifiers info
+ int lastModifiers = ClassFileConstants.AccDefault;
+ int lastModifiersStart = -1;
+
+ // depth of '(', '{' and '[]'
+ int bracketDepth;
+
+ // show if the current token can be an explicit constructor
+ int canBeExplicitConstructor = NO;
+ static final int NO = 0;
+ static final int NEXTTOKEN = 1;
+ static final int YES = 2;
+
+ protected static final int LabelStackIncrement = 10;
+ char[][] labelStack = new char[LabelStackIncrement][];
+ int labelPtr = -1;
+
+ boolean isAlreadyAttached;
+ public boolean record = false;
+ public boolean skipRecord = false;
+ public int recordFrom;
+ public int recordTo;
+ public int potentialVariableNamesPtr;
+ public char[][] potentialVariableNames;
+ public int[] potentialVariableNameStarts;
+ public int[] potentialVariableNameEnds;
+
+public CompletionParser(ProblemReporter problemReporter) {
+ super(problemReporter);
+ this.reportSyntaxErrorIsRequired = false;
+ this.javadocParser.checkDocComment = true;
+}
+private void addPotentialName(char[] potentialVariableName, int start, int end) {
+ int length = this.potentialVariableNames.length;
+ if (this.potentialVariableNamesPtr >= length - 1) {
+ System.arraycopy(
+ this.potentialVariableNames,
+ 0,
+ this.potentialVariableNames = new char[length * 2][],
+ 0,
+ length);
+ System.arraycopy(
+ this.potentialVariableNameStarts,
+ 0,
+ this.potentialVariableNameStarts = new int[length * 2],
+ 0,
+ length);
+ System.arraycopy(
+ this.potentialVariableNameEnds,
+ 0,
+ this.potentialVariableNameEnds = new int[length * 2],
+ 0,
+ length);
+ }
+ this.potentialVariableNames[++this.potentialVariableNamesPtr] = potentialVariableName;
+ this.potentialVariableNameStarts[this.potentialVariableNamesPtr] = start;
+ this.potentialVariableNameEnds[this.potentialVariableNamesPtr] = end;
+}
+public void startRecordingIdentifiers(int from, int to) {
+ this.record = true;
+ this.skipRecord = false;
+ this.recordFrom = from;
+ this.recordTo = to;
+
+ this.potentialVariableNamesPtr = -1;
+ this.potentialVariableNames = new char[10][];
+ this.potentialVariableNameStarts = new int[10];
+ this.potentialVariableNameEnds = new int[10];
+}
+public void stopRecordingIdentifiers() {
+ this.record = true;
+ this.skipRecord = false;
+}
+
+public char[] assistIdentifier(){
+ return ((CompletionScanner)scanner).completionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+ if(assistNode == null || this.isAlreadyAttached) return;
+
+
+ if (STOP_AT_CURSOR)
+ this.isAlreadyAttached = true;
+ if (this.isOrphanCompletionNode) {
+ if (!STOP_AT_CURSOR)
+ this.isAlreadyAttached = true;
+ ASTNode orphan = this.assistNode;
+ this.isOrphanCompletionNode = false;
+
+ if (currentElement instanceof RecoveredUnit){
+ if (orphan instanceof ImportReference){
+ currentElement.add((ImportReference)orphan, 0);
+ }
+ }
+
+ /* if in context of a type, then persists the identifier into a fake field return type */
+ if (currentElement instanceof RecoveredType){
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (recoveredType.foundOpeningBrace) {
+ /* generate a pseudo field with a completion on type reference */
+ if (orphan instanceof TypeReference){
+ TypeReference fieldType;
+
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+ if(kind == K_BINARY_OPERATOR && info == LESS && this.identifierPtr > -1) {
+ this.pushOnGenericsStack(orphan);
+ fieldType = getTypeReference(0);
+ this.assistNodeParent = fieldType;
+ } else {
+ fieldType = (TypeReference)orphan;
+ }
+
+ CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType(fieldType, false);
+
+ // retrieve available modifiers if any
+ if (intPtr >= 2 && intStack[intPtr-1] == this.lastModifiersStart && intStack[intPtr-2] == this.lastModifiers){
+ fieldDeclaration.modifiersSourceStart = intStack[intPtr-1];
+ fieldDeclaration.modifiers = intStack[intPtr-2];
+ }
+
+ currentElement = currentElement.add(fieldDeclaration, 0);
+ return;
+ }
+ }
+ }
+ /* if in context of a method, persists if inside arguments as a type */
+ if (currentElement instanceof RecoveredMethod){
+ RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+ /* only consider if inside method header */
+ if (!recoveredMethod.foundOpeningBrace) {
+ //if (rParenPos < lParenPos){ // inside arguments
+ if (orphan instanceof TypeReference){
+ currentElement = currentElement.parent.add(
+ new CompletionOnFieldType((TypeReference)orphan, true), 0);
+ return;
+ }
+ }
+ }
+
+ if ((topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN)) {
+ if (this.assistNode instanceof CompletionOnSingleTypeReference &&
+ ((CompletionOnSingleTypeReference)this.assistNode).isException()) {
+ buildMoreTryStatementCompletionContext((TypeReference)this.assistNode);
+ return;
+ } else if (this.assistNode instanceof CompletionOnQualifiedTypeReference &&
+ ((CompletionOnQualifiedTypeReference)this.assistNode).isException()) {
+ buildMoreTryStatementCompletionContext((TypeReference)this.assistNode);
+ return;
+ }
+ } // add the completion node to the method declaration or constructor declaration
+ if (orphan instanceof Statement) {
+ /* check for completion at the beginning of method body
+ behind an invalid signature
+ */
+ RecoveredMethod method = currentElement.enclosingMethod();
+ if (method != null){
+ AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+ if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+ && (Util.getLineNumber(orphan.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
+ == Util.getLineNumber(methodDecl.sourceEnd, scanner.lineEnds, 0, scanner.linePtr))){
+ return;
+ }
+ }
+ // add the completion node as a statement to the list of block statements
+ currentElement = currentElement.add((Statement)orphan, 0);
+ return;
+ }
+ }
+
+ if (this.isInsideAnnotation()) {
+ // push top expression on ast stack if it contains the completion node
+ Expression expression;
+ if (this.expressionPtr > -1) {
+ expression = this.expressionStack[this.expressionPtr];
+ if(expression == assistNode) {
+ if (this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_MEMBER_VALUE_ARRAY_INITIALIZER ) {
+ ArrayInitializer arrayInitializer = new ArrayInitializer();
+ arrayInitializer.expressions = new Expression[]{expression};
+ } else if(this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) {
+ if (expression instanceof SingleNameReference) {
+ SingleNameReference nameReference = (SingleNameReference) expression;
+ return;
+ } else if (expression instanceof QualifiedNameReference) {
+ }
+ } else {
+ int index;
+ if((index = lastIndexOfElement(K_ATTRIBUTE_VALUE_DELIMITER)) != -1) {
+ int attributeIndentifierPtr = this.elementInfoStack[index];
+ int identLengthPtr = this.identifierLengthPtr;
+ int identPtr = this.identifierPtr;
+ while (attributeIndentifierPtr < identPtr) {
+ identPtr -= this.identifierLengthStack[identLengthPtr--];
+ }
+
+ if(attributeIndentifierPtr != identPtr) return;
+
+ this.identifierLengthPtr = identLengthPtr;
+ this.identifierPtr = identPtr;
+
+ this.identifierLengthPtr--;
+ this.identifierPtr--;
+
+ return;
+ }
+ }
+ } else {
+ CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, expression);
+ if(detector.containsCompletionNode()) {
+ }
+ }
+ }
+ }
+
+ if(this.currentElement instanceof RecoveredType || this.currentElement instanceof RecoveredMethod) {
+ if(this.currentElement instanceof RecoveredType) {
+ RecoveredType recoveredType = (RecoveredType)this.currentElement;
+ }
+
+ if ((!isInsideMethod() && !isInsideFieldInitialization())) {
+ if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsIdentifiersLengthPtr > -1) {
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+ int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+ int genPtr = this.genericsPtr;
+ done : for(int i = 0; i <= this.identifierLengthPtr && numberOfIdentifiers > 0; i++){
+ int identifierLength = this.identifierLengthStack[this.identifierLengthPtr - i];
+ int length = this.genericsLengthStack[this.genericsLengthPtr - i];
+ for(int j = 0; j < length; j++) {
+ ASTNode node = this.genericsStack[genPtr - j];
+ CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, node);
+ if(detector.containsCompletionNode()) {
+ if(node == this.assistNode){
+ if(this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
+ TypeReference ref = this.getTypeReference(0);
+ this.assistNodeParent = ref;
+ }
+ } else {
+ this.assistNodeParent = detector.getCompletionNodeParent();
+ }
+ break done;
+ }
+ }
+ genPtr -= length;
+ numberOfIdentifiers -= identifierLength;
+ }
+ if(this.assistNodeParent != null && this.assistNodeParent instanceof TypeReference) {
+ if(this.currentElement instanceof RecoveredType) {
+ this.currentElement = this.currentElement.add(new CompletionOnFieldType((TypeReference)this.assistNodeParent, false), 0);
+ } else {
+ this.currentElement = this.currentElement.add((TypeReference)this.assistNodeParent, 0);
+ }
+ }
+ }
+ }
+ }
+
+ // the following code applies only in methods, constructors or initializers
+ if ((!isInsideMethod() && !isInsideFieldInitialization() && !isInsideAttributeValue())) {
+ return;
+ }
+
+ if(this.genericsPtr > -1) {
+ ASTNode node = this.genericsStack[this.genericsPtr];
+ CompletionNodeDetector detector = new CompletionNodeDetector(this.assistNode, node);
+ if(detector.containsCompletionNode()) {
+ /* check for completion at the beginning of method body
+ behind an invalid signature
+ */
+ RecoveredMethod method = this.currentElement.enclosingMethod();
+ if (method != null){
+ AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+ if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+ && (Util.getLineNumber(node.sourceStart, this.scanner.lineEnds, 0, this.scanner.linePtr)
+ == Util.getLineNumber(methodDecl.sourceEnd, this.scanner.lineEnds, 0, this.scanner.linePtr))){
+ return;
+ }
+ }
+ if(node == this.assistNode){
+ buildMoreGenericsCompletionContext(node,true);
+ }
+ }
+ }
+
+ // push top expression on ast stack if it contains the completion node
+ Expression expression;
+ if (this.expressionPtr > -1) {
+ expression = this.expressionStack[this.expressionPtr];
+ CompletionNodeDetector detector = new CompletionNodeDetector(assistNode, expression);
+ if(detector.containsCompletionNode()) {
+ /* check for completion at the beginning of method body
+ behind an invalid signature
+ */
+ RecoveredMethod method = currentElement.enclosingMethod();
+ if (method != null){
+ AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+ if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+ && (Util.getLineNumber(expression.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
+ == Util.getLineNumber(methodDecl.sourceEnd, scanner.lineEnds, 0, scanner.linePtr))){
+ return;
+ }
+ }
+ if(expression == assistNode
+ || (expression instanceof AllocationExpression
+ && ((AllocationExpression)expression).type == assistNode)){
+ buildMoreCompletionContext(expression);
+ } else {
+ assistNodeParent = detector.getCompletionNodeParent();
+ if(assistNodeParent != null) {
+ currentElement = currentElement.add((Statement)assistNodeParent, 0);
+ } else {
+ currentElement = currentElement.add(expression, 0);
+ }
+ }
+ }
+ }
+}
+
+private void buildMoreCompletionContext(Expression expression) {
+ Statement statement = expression;
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ if(kind != 0) {
+ int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+ nextElement : switch (kind) {
+ case K_SELECTOR_QUALIFIER :
+ int selector = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 2);
+ if(false){// Not Possible selector == THIS_CONSTRUCTOR || selector == SUPER_CONSTRUCTOR) {
+ ExplicitConstructorCall call = new ExplicitConstructorCall(ExplicitConstructorCall.This);
+ call.arguments = new Expression[] {expression};
+ call.sourceStart = expression.sourceStart;
+ call.sourceEnd = expression.sourceEnd;
+ assistNodeParent = call;
+ } else {
+ int invocType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER,1);
+ int qualifierExprPtr = info;
+
+ // find arguments
+ int length = expressionLengthStack[expressionLengthPtr];
+
+ // search previous arguments if missing
+ if(this.expressionPtr > 0 && this.expressionLengthPtr > 0 && length == 1) {
+ int start = 0;
+ if (invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION)
+ start=(int) (identifierPositionStack[selector] >>> 32);
+ else
+ start=expressionStack[info].sourceStart;
+
+ if(this.expressionStack[expressionPtr-1] != null && this.expressionStack[expressionPtr-1].sourceStart > start) {
+ length += expressionLengthStack[expressionLengthPtr-1];
+ }
+
+ }
+
+ Expression[] arguments = null;
+ if (length != 0) {
+ arguments = new Expression[length];
+ expressionPtr -= length;
+ System.arraycopy(expressionStack, expressionPtr + 1, arguments, 0, length-1);
+ arguments[length-1] = expression;
+ }
+
+ if(invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) {
+ MessageSend messageSend = new MessageSend();
+ messageSend.selector = identifierStack[selector];
+ messageSend.arguments = arguments;
+
+ // find receiver
+ switch (invocType) {
+ case NO_RECEIVER:
+ messageSend.receiver = ThisReference.implicitThis();
+ break;
+ case NAME_RECEIVER:
+ // remove special flags for primitive types
+ while (this.identifierLengthPtr >= 0 && this.identifierLengthStack[this.identifierLengthPtr] < 0) {
+ this.identifierLengthPtr--;
+ }
+
+ // remove selector
+ this.identifierPtr--;
+ if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsLengthStack[this.genericsLengthPtr] > 0) {
+ // is inside a paremeterized method: bar..foo
+ this.identifierLengthPtr--;
+ } else {
+ this.identifierLengthStack[this.identifierLengthPtr]--;
+ }
+ // consume the receiver
+ int identifierLength = this.identifierLengthStack[this.identifierLengthPtr];
+ if(this.identifierPtr > -1 && identifierLength > 0 && this.identifierPtr + 1 >= identifierLength) {
+ messageSend.receiver = this.getUnspecifiedReference();
+ } else {
+ messageSend = null;
+ }
+ break;
+ case SUPER_RECEIVER:
+ messageSend.receiver = new SuperReference(0, 0);
+ break;
+ case EXPLICIT_RECEIVER:
+ messageSend.receiver = this.expressionStack[qualifierExprPtr];
+ break;
+ default :
+ messageSend.receiver = ThisReference.implicitThis();
+ break;
+ }
+ assistNodeParent = messageSend;
+ } else {
+ if(invocType == ALLOCATION) {
+ AllocationExpression allocationExpr = new AllocationExpression();
+ allocationExpr.arguments = arguments;
+// pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+// pushOnGenericsLengthStack(0);
+// allocationExpr.type = getTypeReference(0);
+ allocationExpr.member=expressionStack[info];
+ assistNodeParent = allocationExpr;
+ } else {
+ QualifiedAllocationExpression allocationExpr = new QualifiedAllocationExpression();
+ allocationExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
+ allocationExpr.arguments = arguments;
+ pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+
+ allocationExpr.type = getTypeReference(0);
+ assistNodeParent = allocationExpr;
+ }
+ }
+ }
+ break nextElement;
+ case K_INSIDE_RETURN_STATEMENT :
+ if(info == bracketDepth) {
+ ReturnStatement returnStatement = new ReturnStatement(expression, expression.sourceStart, expression.sourceEnd);
+ assistNodeParent = returnStatement;
+ }
+ break nextElement;
+ case K_UNARY_OPERATOR :
+ if(expressionPtr > -1) {
+ Expression operatorExpression = null;
+ switch (info) {
+ case PLUS_PLUS :
+ operatorExpression = new PrefixExpression(expression,IntLiteral.getOne(), PLUS, expression.sourceStart);
+ break;
+ case MINUS_MINUS :
+ operatorExpression = new PrefixExpression(expression,IntLiteral.getOne(), MINUS, expression.sourceStart);
+ break;
+ default :
+ operatorExpression = new UnaryExpression(expression, info);
+ break;
+ }
+ assistNodeParent = operatorExpression;
+ }
+ break nextElement;
+ case K_BINARY_OPERATOR :
+ if(expressionPtr > -1) {
+ Expression operatorExpression = null;
+ Expression left = null;
+ if(expressionPtr == 0) {
+ // it is a ***_NotName rule
+ if(this.identifierPtr > -1) {
+ left = getUnspecifiedReferenceOptimized();
+ }
+ } else {
+ left = this.expressionStack[expressionPtr-1];
+ // is it a ***_NotName rule ?
+ if(this.identifierPtr > -1) {
+ int start = (int) (identifierPositionStack[this.identifierPtr] >>> 32);
+ if(left.sourceStart < start) {
+ left = getUnspecifiedReferenceOptimized();
+ }
+ }
+ }
+
+ if(left != null) {
+ switch (info) {
+ case AND_AND :
+ operatorExpression = new AND_AND_Expression(left, expression, info);
+ break;
+ case OR_OR :
+ operatorExpression = new OR_OR_Expression(left, expression, info);
+ break;
+ case EQUAL_EQUAL :
+ case NOT_EQUAL :
+ operatorExpression = new EqualExpression(left, expression, info);
+ break;
+ default :
+ operatorExpression = new BinaryExpression(left, expression, info);
+ break;
+ }
+ }
+ if(operatorExpression != null) {
+ assistNodeParent = operatorExpression;
+ }
+ }
+ break nextElement;
+ case K_ARRAY_INITIALIZER :
+ ArrayInitializer arrayInitializer = new ArrayInitializer();
+ arrayInitializer.expressions = new Expression[]{expression};
+ expressionPtr -= expressionLengthStack[expressionLengthPtr--];
+
+ if(expressionLengthPtr > -1
+ && expressionPtr > -1
+ && this.expressionStack[expressionPtr] != null
+ && this.expressionStack[expressionPtr].sourceStart > info) {
+ expressionLengthPtr--;
+ }
+
+ lastCheckPoint = scanner.currentPosition;
+
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_ARRAY_CREATION) {
+ ArrayAllocationExpression allocationExpression = new ArrayAllocationExpression();
+ pushOnGenericsLengthStack(0);
+ pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+ allocationExpression.type = getTypeReference(0);
+ allocationExpression.type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage
+ int length = expressionLengthStack[expressionLengthPtr];
+ allocationExpression.dimensions = new Expression[length];
+
+ allocationExpression.initializer = arrayInitializer;
+ assistNodeParent = allocationExpression;
+ } else if(currentElement instanceof RecoveredField && !(currentElement instanceof RecoveredInitializer)) {
+ RecoveredField recoveredField = (RecoveredField) currentElement;
+ if(recoveredField.fieldDeclaration.type.dimensions() == 0) {
+ Block block = new Block(0);
+ block.sourceStart = info;
+ currentElement = currentElement.add(block, 1);
+ } else {
+ statement = arrayInitializer;
+ }
+ } else if(currentElement instanceof RecoveredLocalVariable) {
+ RecoveredLocalVariable recoveredLocalVariable = (RecoveredLocalVariable) currentElement;
+ if(recoveredLocalVariable.localDeclaration.type.dimensions() == 0) {
+ Block block = new Block(0);
+ block.sourceStart = info;
+ currentElement = currentElement.add(block, 1);
+ } else {
+ statement = arrayInitializer;
+ }
+ } else {
+ statement = arrayInitializer;
+ }
+ break nextElement;
+ case K_ARRAY_CREATION :
+ ArrayAllocationExpression allocationExpression = new ArrayAllocationExpression();
+ allocationExpression.type = getTypeReference(0);
+ allocationExpression.dimensions = new Expression[]{expression};
+
+ assistNodeParent = allocationExpression;
+ break nextElement;
+ case K_ASSISGNMENT_OPERATOR :
+ if(expressionPtr > 0 && expressionStack[expressionPtr - 1] != null) {
+ Assignment assignment;
+ if(info == EQUAL) {
+ assignment = new Assignment(
+ expressionStack[expressionPtr - 1],
+ expression,
+ expression.sourceEnd
+ );
+ } else {
+ assignment = new CompoundAssignment(
+ expressionStack[expressionPtr - 1],
+ expression,
+ info,
+ expression.sourceEnd
+ );
+ }
+ assistNodeParent = assignment;
+ }
+ break nextElement;
+ case K_CONDITIONAL_OPERATOR :
+ if(info == QUESTION) {
+ if(expressionPtr > 0) {
+ expressionPtr--;
+ expressionLengthPtr--;
+ expressionStack[expressionPtr] = expressionStack[expressionPtr+1];
+ popElement(K_CONDITIONAL_OPERATOR);
+ buildMoreCompletionContext(expression);
+ return;
+ }
+ } else {
+ if(expressionPtr > 1) {
+ expressionPtr = expressionPtr - 2;
+ expressionLengthPtr = expressionLengthPtr - 2;
+ expressionStack[expressionPtr] = expressionStack[expressionPtr+2];
+ popElement(K_CONDITIONAL_OPERATOR);
+ buildMoreCompletionContext(expression);
+ return;
+ }
+ }
+ break nextElement;
+ case K_BETWEEN_LEFT_AND_RIGHT_BRACKET :
+ ArrayReference arrayReference;
+ if(identifierPtr < 0 && expressionPtr > 0 && expressionStack[expressionPtr] == expression) {
+ arrayReference =
+ new ArrayReference(
+ expressionStack[expressionPtr-1],
+ expression);
+ } else {
+ arrayReference =
+ new ArrayReference(
+ getUnspecifiedReferenceOptimized(),
+ expression);
+ }
+ assistNodeParent = arrayReference;
+ break;
+ case K_BETWEEN_CASE_AND_COLON :
+ if(this.expressionPtr > 0) {
+ SwitchStatement switchStatement = new SwitchStatement();
+ switchStatement.expression = this.expressionStack[this.expressionPtr - 1];
+ if(this.astLengthPtr > -1 && this.astPtr > -1) {
+ int length = this.astLengthStack[this.astLengthPtr];
+ int newAstPtr = this.astPtr - length;
+ ASTNode firstNode = this.astStack[newAstPtr + 1];
+ if(length != 0 && firstNode.sourceStart > switchStatement.expression.sourceEnd) {
+ switchStatement.statements = new Statement[length + 1];
+ System.arraycopy(
+ this.astStack,
+ newAstPtr + 1,
+ switchStatement.statements,
+ 0,
+ length);
+ }
+ }
+ CaseStatement caseStatement = new CaseStatement(expression, expression.sourceStart, expression.sourceEnd);
+ if(switchStatement.statements == null) {
+ switchStatement.statements = new Statement[]{caseStatement};
+ } else {
+ switchStatement.statements[switchStatement.statements.length - 1] = caseStatement;
+ }
+ assistNodeParent = switchStatement;
+ }
+ break;
+ }
+ }
+ if(assistNodeParent != null) {
+ currentElement = currentElement.add((Statement)assistNodeParent, 0);
+ } else {
+ if(currentElement instanceof RecoveredField && !(currentElement instanceof RecoveredInitializer)
+ && ((RecoveredField) currentElement).fieldDeclaration.initialization == null) {
+
+ assistNodeParent = ((RecoveredField) currentElement).fieldDeclaration;
+ currentElement = currentElement.add(statement, 0);
+ } else if(currentElement instanceof RecoveredLocalVariable
+ && ((RecoveredLocalVariable) currentElement).localDeclaration.initialization == null) {
+
+ assistNodeParent = ((RecoveredLocalVariable) currentElement).localDeclaration;
+ currentElement = currentElement.add(statement, 0);
+ } else {
+ currentElement = currentElement.add(expression, 0);
+ }
+ }
+}
+private void buildMoreGenericsCompletionContext(ASTNode node, boolean consumeTypeArguments) {
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ if(kind != 0) {
+ int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+ nextElement : switch (kind) {
+ case K_BINARY_OPERATOR :
+ int prevKind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1);
+ switch (prevKind) {
+ case K_PARAMETERIZED_ALLOCATION :
+ if(this.invocationType == ALLOCATION || this.invocationType == QUALIFIED_ALLOCATION) {
+ currentElement = currentElement.add((TypeReference)node, 0);
+ }
+ break nextElement;
+ case K_PARAMETERIZED_METHOD_INVOCATION :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == 0) {
+ currentElement = currentElement.add((TypeReference)node, 0);
+ break nextElement;
+ }
+ }
+ if(info == LESS && node instanceof TypeReference) {
+ if(this.identifierLengthPtr > -1 && this.identifierLengthStack[this.identifierLengthPtr]!= 0) {
+ TypeReference ref = this.getTypeReference(0);
+ if(currentElement instanceof RecoveredType) {
+ currentElement = currentElement.add(new CompletionOnFieldType(ref, false), 0);
+ } else {
+ currentElement = currentElement.add(ref, 0);
+ }
+ } else if (currentElement.enclosingMethod().methodDeclaration.isConstructor()) {
+ currentElement = currentElement.add((TypeReference)node, 0);
+ }
+ }
+ break;
+ }
+ }
+}
+private void buildMoreTryStatementCompletionContext(TypeReference exceptionRef) {
+ if (this.astLengthPtr > -1 &&
+ this.astPtr > 1 &&
+ this.astStack[this.astPtr] instanceof Block &&
+ this.astStack[this.astPtr - 1] instanceof Argument) {
+ TryStatement tryStatement = new TryStatement();
+
+ int newAstPtr = this.astPtr;
+
+ int length = this.astLengthStack[this.astLengthPtr];
+ Block[] bks = (tryStatement.catchBlocks = new Block[length + 1]);
+ Argument[] args = (tryStatement.catchArguments = new Argument[length + 1]);
+ if (length != 0) {
+ while (length-- > 0) {
+ bks[length] = (Block) this.astStack[newAstPtr--];
+ bks[length].statements = null; // statements of catch block won't be used
+ args[length] = (Argument) this.astStack[newAstPtr--];
+ }
+ }
+
+ bks[bks.length - 1] = new Block(0);
+ args[args.length - 1] = new Argument(FAKE_ARGUMENT_NAME,0,exceptionRef,0);
+
+ tryStatement.tryBlock = (Block) this.astStack[newAstPtr--];
+
+ assistNodeParent = tryStatement;
+
+ currentElement.add(tryStatement, 0);
+ } else if (this.astLengthPtr > -1 &&
+ this.astPtr > -1 &&
+ this.astStack[this.astPtr] instanceof Block) {
+ TryStatement tryStatement = new TryStatement();
+
+ int newAstPtr = this.astPtr;
+
+ Block[] bks = (tryStatement.catchBlocks = new Block[1]);
+ Argument[] args = (tryStatement.catchArguments = new Argument[1]);
+
+ bks[0] = new Block(0);
+ args[0] = new Argument(FAKE_ARGUMENT_NAME,0,exceptionRef,0);
+
+ tryStatement.tryBlock = (Block) this.astStack[newAstPtr--];
+
+ assistNodeParent = tryStatement;
+
+ currentElement.add(tryStatement, 0);
+ }else {
+ currentElement = currentElement.add(exceptionRef, 0);
+ }
+}
+
+public int bodyEnd(AbstractMethodDeclaration method){
+ return cursorLocation;
+}
+public int bodyEnd(Initializer initializer){
+ return cursorLocation;
+}
+/**
+ * Checks if the completion is on the exception type of a catch clause.
+ * Returns whether we found a completion node.
+ */
+private boolean checkCatchClause() {
+ if ((topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN) && this.identifierPtr > -1) {
+ // NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1),
+ // thus this can only be a completion on the type of the catch clause
+ pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
+ this.assistNode = getTypeReference(0);
+ popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on the type following a 'new'.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassInstanceCreation() {
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_NEW_AND_LEFT_BRACKET) {
+ int length = identifierLengthStack[identifierLengthPtr];
+ int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+ if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+ // no class instance creation with a parameterized type
+ return true;
+ }
+
+ // completion on type inside an allocation expression
+
+ TypeReference type;
+ if (this.invocationType == ALLOCATION) {
+ // non qualified allocation expression
+ AllocationExpression allocExpr = new AllocationExpression();
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
+ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
+ pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
+ type = getTypeReference(0);
+ popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
+ } else {
+ type = getTypeReference(0);
+ }
+ if(type instanceof CompletionOnSingleTypeReference) {
+ ((CompletionOnSingleTypeReference)type).isConstructorType = true;
+ }
+ allocExpr.type = type;
+ allocExpr.sourceStart = type.sourceStart;
+ allocExpr.sourceEnd = type.sourceEnd;
+ pushOnExpressionStack(allocExpr);
+ this.isOrphanCompletionNode = false;
+ } else {
+ // qualified allocation expression
+ QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
+ pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_INSIDE_THROW_STATEMENT
+ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == this.bracketDepth) {
+ pushOnElementStack(K_NEXT_TYPEREF_IS_EXCEPTION);
+ type = getTypeReference(0);
+ popElement(K_NEXT_TYPEREF_IS_EXCEPTION);
+ } else {
+ type = getTypeReference(0);
+ }
+ allocExpr.type = type;
+ allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
+ allocExpr.sourceStart = this.intStack[this.intPtr--];
+ allocExpr.sourceEnd = type.sourceEnd;
+ this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
+ this.isOrphanCompletionNode = false;
+ }
+ this.assistNode = type;
+ this.lastCheckPoint = type.sourceEnd + 1;
+
+ popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on the dot following an array type,
+ * a primitive type or an primitive array type.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassLiteralAccess() {
+ if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
+ int length;
+ // if the penultimate id length is negative,
+ // the completion is after a primitive type or a primitive array type
+ if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
+ // build the primitive type node
+ int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
+ SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
+ typeRef.sourceStart = this.intStack[this.intPtr--];
+ if (dim == 0) {
+ typeRef.sourceEnd = this.intStack[this.intPtr--];
+ } else {
+ this.intPtr--;
+ typeRef.sourceEnd = this.endPosition;
+ }
+ //typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
+
+ // find the completion identifier and its source positions
+ char[] source = identifierStack[identifierPtr];
+ long pos = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+
+ // build the completion on class literal access node
+ CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+ access.completionIdentifier = source;
+ this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
+ this.assistNode = access;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+
+ // if the completion is after a regular array type
+ if (isAfterArrayType()) {
+ // find the completion identifier and its source positions
+ char[] source = identifierStack[identifierPtr];
+ long pos = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+
+ // get the type reference
+ pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+
+ TypeReference typeRef = getTypeReference(this.intStack[this.intPtr--]);
+
+ // build the completion on class literal access node
+ CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+ access.completionIdentifier = source;
+ this.assistNode = access;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+
+ }
+ return false;
+}
+private boolean checkKeyword() {
+ if (currentElement instanceof RecoveredUnit) {
+// RecoveredUnit unit = (RecoveredUnit) currentElement;
+ int index = -1;
+ if ((index = this.indexOfAssistIdentifier()) > -1) {
+ int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
+
+ char[] ident = identifierStack[ptr];
+ long pos = identifierPositionStack[ptr];
+
+ char[][] keywords = new char[Keywords.COUNT][];
+ int count = 0;
+// if(unit.typeCount == 0
+// && lastModifiers == ClassFileConstants.AccDefault) {
+// keywords[count++] = Keywords.IMPORT;
+// }
+// if(unit.typeCount == 0
+// && unit.importCount == 0
+// && lastModifiers == ClassFileConstants.AccDefault
+// && compilationUnit.currentPackage == null) {
+// keywords[count++] = Keywords.PACKAGE;
+// }
+// if((lastModifiers & ClassFileConstants.AccPublic) == 0) {
+// boolean hasNoPublicType = true;
+// for (int i = 0; i < unit.typeCount; i++) {
+// if((unit.types[i].typeDeclaration.modifiers & ClassFileConstants.AccPublic) != 0) {
+// hasNoPublicType = false;
+// }
+// }
+// if(hasNoPublicType) {
+// keywords[count++] = Keywords.PUBLIC;
+// }
+// }
+// if((lastModifiers & ClassFileConstants.AccAbstract) == 0
+// && (lastModifiers & ClassFileConstants.AccFinal) == 0) {
+// keywords[count++] = Keywords.ABSTRACT;
+// }
+// if((lastModifiers & ClassFileConstants.AccAbstract) == 0
+// && (lastModifiers & ClassFileConstants.AccFinal) == 0) {
+// keywords[count++] = Keywords.FINAL;
+// }
+//
+// keywords[count++] = Keywords.CLASS;
+//
+// if((lastModifiers & ClassFileConstants.AccFinal) == 0) {
+// keywords[count++] = Keywords.INTERFACE;
+// }
+ if(count != 0) {
+ System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
+
+ this.assistNode = new CompletionOnKeyword2(ident, pos, keywords);
+ this.lastCheckPoint = assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+private boolean checkInstanceofKeyword() {
+ if(isInsideMethod()) {
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ int index;
+ if(kind != K_BLOCK_DELIMITER
+ && (index = indexOfAssistIdentifier()) > -1
+ && expressionPtr > -1
+ && expressionLengthStack[expressionPtr] == 1) {
+
+ int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
+ if(identifierStack[ptr].length > 0 && CharOperation.prefixEquals(identifierStack[ptr], Keywords.INSTANCEOF)) {
+ this.assistNode = new CompletionOnKeyword3(
+ identifierStack[ptr],
+ identifierPositionStack[ptr],
+ Keywords.INSTANCEOF);
+ this.lastCheckPoint = assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ if(identifierStack[ptr].length > 0 && CharOperation.prefixEquals(identifierStack[ptr], Keywords.TYPEOF)) {
+ this.assistNode = new CompletionOnKeyword3(
+ identifierStack[ptr],
+ identifierPositionStack[ptr],
+ Keywords.TYPEOF);
+ this.lastCheckPoint = assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+/**
+ * Checks if the completion is inside a method invocation or a constructor invocation.
+ * Returns whether we found a completion node.
+ */
+private boolean checkInvocation() {
+ Expression topExpression = this.expressionPtr >= 0 ?
+ this.expressionStack[this.expressionPtr] :
+ null;
+ boolean isEmptyNameCompletion = false;
+ boolean isEmptyAssistIdentifier = false;
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR_QUALIFIER
+ && ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
+ || (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
+
+ // pop empty name completion
+ if (isEmptyNameCompletion) {
+ this.expressionPtr--;
+ this.expressionLengthStack[this.expressionLengthPtr]--;
+ } else if (isEmptyAssistIdentifier) {
+ this.identifierPtr--;
+ this.identifierLengthPtr--;
+ }
+
+ // find receiver and qualifier
+ int invocType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1);
+ int qualifierExprPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+
+ // find arguments
+ int numArgs = this.expressionPtr - qualifierExprPtr;
+ int argStart = qualifierExprPtr + 1;
+ Expression[] arguments = null;
+ if (numArgs > 0) {
+ // remember the arguments
+ arguments = new Expression[numArgs];
+ System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
+
+ // consume the expression arguments
+ this.expressionPtr -= numArgs;
+ int count = numArgs;
+ while (count > 0) {
+ count -= this.expressionLengthStack[this.expressionLengthPtr--];
+ }
+ }
+
+ // build ast node
+ if (invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) {
+ // creates completion on message send
+ CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
+ messageSend.arguments = arguments;
+ switch (invocType) {
+ case NO_RECEIVER:
+ // implicit this
+ messageSend.receiver = ThisReference.implicitThis();
+ break;
+ case NAME_RECEIVER:
+ // remove special flags for primitive types
+ while (this.identifierLengthPtr >= 0 && this.identifierLengthStack[this.identifierLengthPtr] < 0) {
+ this.identifierLengthPtr--;
+ }
+
+ // remove selector
+ this.identifierPtr--;
+ if(this.genericsPtr > -1 && this.genericsLengthPtr > -1 && this.genericsLengthStack[this.genericsLengthPtr] > 0) {
+ // is inside a paremeterized method: bar..foo
+ this.identifierLengthPtr--;
+ } else {
+ this.identifierLengthStack[this.identifierLengthPtr]--;
+ }
+ // consume the receiver
+ messageSend.receiver = this.getUnspecifiedReference();
+ break;
+ case SUPER_RECEIVER:
+ messageSend.receiver = new SuperReference(0, 0);
+ break;
+ case EXPLICIT_RECEIVER:
+ messageSend.receiver = this.expressionStack[qualifierExprPtr];
+ }
+
+ // set selector
+ int selectorPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 2);
+ messageSend.selector = this.identifierStack[selectorPtr];
+ // remove selector
+ if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
+ this.identifierPtr--;
+ this.identifierLengthPtr--;
+ }
+
+ // the entire message may be replaced in case qualification is needed
+ messageSend.sourceStart = (int)(this.identifierPositionStack[selectorPtr] >> 32); //this.cursorLocation + 1;
+ messageSend.sourceEnd = this.cursorLocation;
+
+ // remember the message send as an orphan completion node
+ this.assistNode = messageSend;
+ this.lastCheckPoint = messageSend.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ } else {
+ int selectorPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 2);
+ if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
+ // creates an explicit constructor call
+ CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(ExplicitConstructorCall.This);
+ call.arguments = arguments;
+ if (invocType == QUALIFIED_ALLOCATION) {
+ call.qualification = this.expressionStack[qualifierExprPtr];
+ }
+
+ // no source is going to be replaced
+ call.sourceStart = this.cursorLocation + 1;
+ call.sourceEnd = this.cursorLocation;
+
+ // remember the explicit constructor call as an orphan completion node
+ this.assistNode = call;
+ this.lastCheckPoint = call.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ } else {
+ // creates an allocation expression
+ CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
+ allocExpr.arguments = arguments;
+ if(this.genericsLengthPtr < 0) {
+ pushOnGenericsLengthStack(0);
+ pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+ }
+ allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
+ if (invocType == QUALIFIED_ALLOCATION) {
+ allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
+ }
+ // no source is going to be replaced
+ allocExpr.sourceStart = this.cursorLocation + 1;
+ allocExpr.sourceEnd = this.cursorLocation;
+
+ // remember the allocation expression as an orphan completion node
+ this.assistNode = allocExpr;
+ this.lastCheckPoint = allocExpr.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+private boolean checkLabelStatement() {
+ if(isInsideMethod() || isInsideFieldInitialization()) {
+
+ int kind = this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ if(kind != K_INSIDE_BREAK_STATEMENT && kind != K_INSIDE_CONTINUE_STATEMENT) return false;
+
+ if (indexOfAssistIdentifier() != 0) return false;
+
+ char[][] labels = new char[this.labelPtr + 1][];
+ int labelCount = 0;
+
+ int labelKind = kind;
+ int index = 1;
+ while(labelKind != 0 && labelKind != K_METHOD_DELIMITER) {
+ labelKind = this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, index);
+ if(labelKind == K_LABEL) {
+ int ptr = this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, index);
+ labels[labelCount++] = this.labelStack[ptr];
+ }
+ index++;
+ }
+ System.arraycopy(labels, 0, labels = new char[labelCount][], 0, labelCount);
+
+ long position = this.identifierPositionStack[this.identifierPtr];
+ CompletionOnBrankStatementLabel statementLabel =
+ new CompletionOnBrankStatementLabel(
+ kind == K_INSIDE_BREAK_STATEMENT ? CompletionOnBrankStatementLabel.BREAK : CompletionOnBrankStatementLabel.CONTINUE,
+ this.identifierStack[this.identifierPtr--],
+ (int) (position >>> 32),
+ (int)position,
+ labels);
+
+ this.assistNode = statementLabel;
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on a member access (ie. in an identifier following a dot).
+ * Returns whether we found a completion node.
+ */
+private boolean checkMemberAccess() {
+ if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
+ if (this.identifierLengthPtr > 1 && this.identifierLengthStack[this.identifierLengthPtr - 1] < 0) {
+ // its not a member access because the receiver is a base type
+ // fix for bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=137623
+ return false;
+ }
+ // the receiver is an expression
+ pushCompletionOnMemberAccessOnExpressionStack(false);
+ return true;
+ }
+ return false;
+}
+/**
+ * Checks if the completion is on a name reference.
+ * Returns whether we found a completion node.
+ */
+private boolean checkNameCompletion() {
+ /*
+ We didn't find any other completion, but the completion identifier is on the identifier stack,
+ so it can only be a completion on name.
+ Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
+ be a completion on 'b'). This policy gives more to the user than he/she would expect, but this
+ simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
+ instead of at the 'expression' granularity as it does right now.
+ */
+
+ // NB: at this point the completion identifier is on the identifier stack
+ this.assistNode = getUnspecifiedReferenceOptimized();
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+}
+/**
+ * Checks if the completion is in the context of a method and on the type of one of its arguments
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredMethod() {
+ if (currentElement instanceof RecoveredMethod){
+ /* check if current awaiting identifier is the completion identifier */
+ if (this.indexOfAssistIdentifier() < 0) return false;
+
+ /* check if on line with an error already - to avoid completing inside
+ illegal type names e.g. int[ */
+ if (lastErrorEndPosition <= cursorLocation+1
+ && Util.getLineNumber(lastErrorEndPosition, scanner.lineEnds, 0, scanner.linePtr)
+ == Util.getLineNumber(((CompletionScanner)scanner).completedIdentifierStart, scanner.lineEnds, 0, scanner.linePtr)){
+ return false;
+ }
+ RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+ /* only consider if inside method header */
+ if (!recoveredMethod.foundOpeningBrace
+ && lastIgnoredToken == -1) {
+ //if (rParenPos < lParenPos){ // inside arguments
+ this.assistNode = this.getTypeReference(0);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ return false;
+}
+/**
+ * Checks if the completion is in the context of a type and on a type reference in this type.
+ * Persists the identifier into a fake field return type
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredType() {
+ if (currentElement instanceof RecoveredType){
+ /* check if current awaiting identifier is the completion identifier */
+ if (this.indexOfAssistIdentifier() < 0) return false;
+
+ /* check if on line with an error already - to avoid completing inside
+ illegal type names e.g. int[ */
+ if ((lastErrorEndPosition <= cursorLocation+1)
+ && Util.getLineNumber(lastErrorEndPosition, scanner.lineEnds, 0, scanner.linePtr)
+ == Util.getLineNumber(((CompletionScanner)scanner).completedIdentifierStart, scanner.lineEnds, 0, scanner.linePtr)){
+ return false;
+ }
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (recoveredType.foundOpeningBrace) {
+ // complete generics stack if necessary
+ if((this.genericsIdentifiersLengthPtr < 0 && this.identifierPtr > -1)
+ || (this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] <= this.identifierPtr)) {
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0); // handle type arguments
+ }
+ this.assistNode = this.getTypeReference(0);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ } else {
+ if(recoveredType.typeDeclaration.superclass == null &&
+ this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_EXTENDS_KEYWORD) {
+ this.consumeClassOrInterfaceName();
+ this.pushOnElementStack(K_NEXT_TYPEREF_IS_CLASS);
+ this.assistNode = this.getTypeReference(0);
+ this.popElement(K_NEXT_TYPEREF_IS_CLASS);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+private void classHeaderExtendsOrImplements(boolean isInterface) {
+ if (currentElement != null
+ && currentToken == TokenNameIdentifier
+ && this.cursorLocation+1 >= scanner.startPosition
+ && this.cursorLocation < scanner.currentPosition){
+ this.pushIdentifier();
+ int index = -1;
+ /* check if current awaiting identifier is the completion identifier */
+ if ((index = this.indexOfAssistIdentifier()) > -1) {
+ int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (!recoveredType.foundOpeningBrace) {
+ TypeDeclaration type = recoveredType.typeDeclaration;
+ if(!isInterface) {
+ char[][] keywords = new char[Keywords.COUNT][];
+ int count = 0;
+
+
+ if(type.superclass == null) {
+ keywords[count++] = Keywords.EXTENDS;
+ }
+ keywords[count++] = Keywords.IMPLEMENTS;
+
+ System.arraycopy(keywords, 0, keywords = new char[count][], 0, count);
+
+ if(count > 0) {
+ CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
+ identifierStack[ptr],
+ identifierPositionStack[ptr],
+ keywords);
+ completionOnKeyword.canCompleteEmptyToken = true;
+ type.superclass = completionOnKeyword;
+ type.superclass.bits |= ASTNode.IsSuperType;
+ this.assistNode = completionOnKeyword;
+ this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
+ }
+ } else {
+ CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
+ identifierStack[ptr],
+ identifierPositionStack[ptr],
+ Keywords.EXTENDS);
+ completionOnKeyword.canCompleteEmptyToken = true;
+ this.assistNode = completionOnKeyword;
+ this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
+ }
+ }
+ }
+ }
+}
+/*
+ * Check whether about to shift beyond the completion token.
+ * If so, depending on the context, a special node might need to be created
+ * and attached to the existing recovered structure so as to be remember in the
+ * resulting parsed structure.
+ */
+public void completionIdentifierCheck(){
+ //if (assistNode != null) return;
+
+ if (checkKeyword()) return;
+ if (checkRecoveredType()) return;
+ if (checkRecoveredMethod()) return;
+
+ // if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
+// if (!(isInsideMethod() && !this.diet)
+// && !isIndirectlyInsideFieldInitialization()
+// && !isInsideAttributeValue()) return;
+
+ /*
+ In some cases, the completion identifier may not have yet been consumed,
+ e.g. int.[cursor]
+ This is because the grammar does not allow any (empty) identifier to follow
+ a base type. We thus have to manually force the identifier to be consumed
+ (that is, pushed).
+ */
+ if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
+ if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
+ this.pushIdentifier();
+ } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
+ this.pushIdentifier();
+ }
+ }
+
+ // check for different scenarii
+ // no need to go further if we found a non empty completion node
+ // (we still need to store labels though)
+ if (this.assistNode != null) {
+ // however inside an invocation, the completion identifier may already have been consumed into an empty name
+ // completion, so this check should be before we check that we are at the cursor location
+ if (!isEmptyNameCompletion() || checkInvocation()) return;
+ }
+
+ // no need to check further if we are not at the cursor location
+ if (this.indexOfAssistIdentifier() < 0) return;
+
+ if (checkClassInstanceCreation()) return;
+ if (checkCatchClause()) return;
+ if (checkMemberAccess()) return;
+ if (checkClassLiteralAccess()) return;
+ if (checkInstanceofKeyword()) return;
+
+ // if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
+ // (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
+ if (checkInvocation()) return;
+
+ if (checkLabelStatement()) return;
+ if (checkNameCompletion()) return;
+}
+protected void consumeArrayCreationHeader() {
+ // nothing to do
+}
+protected void consumeAssignment() {
+ popElement(K_ASSISGNMENT_OPERATOR);
+ super.consumeAssignment();
+}
+protected void consumeAssignmentOperator(int pos) {
+ super.consumeAssignmentOperator(pos);
+ pushOnElementStack(K_ASSISGNMENT_OPERATOR, pos);
+}
+protected void consumeBinaryExpression(int op) {
+ super.consumeBinaryExpression(op);
+ popElement(K_BINARY_OPERATOR);
+
+ if(expressionStack[expressionPtr] instanceof BinaryExpression) {
+ BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
+ if(assistNode != null && exp.right == assistNode) {
+ assistNodeParent = exp;
+ }
+ }
+}
+protected void consumeCaseLabel() {
+ super.consumeCaseLabel();
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_SWITCH_LABEL) {
+ pushOnElementStack(K_SWITCH_LABEL);
+ }
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeCompilationUnit()
+ */
+protected void consumeCompilationUnit() {
+ this.javadoc = null;
+ checkComment();
+ if (this.javadoc != null && this.cursorLocation > this.javadoc.sourceStart && this.cursorLocation < this.javadoc.sourceEnd) {
+ // completion is in an orphan javadoc comment => replace compilation unit one to allow completion resolution
+ compilationUnit.javadoc = this.javadoc;
+ }
+ super.consumeCompilationUnit();
+}
+
+protected void consumeConditionalExpression(int op) {
+ popElement(K_CONDITIONAL_OPERATOR);
+ super.consumeConditionalExpression(op);
+}
+protected void consumeDefaultLabel() {
+ super.consumeDefaultLabel();
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
+ popElement(K_SWITCH_LABEL);
+ }
+ pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
+}
+protected void consumeDimWithOrWithOutExpr() {
+ // DimWithOrWithOutExpr ::= '[' ']'
+ pushOnExpressionStack(null);
+}
+protected void consumeEnterVariable() {
+ identifierPtr--;
+ identifierLengthPtr--;
+
+ boolean isLocalDeclaration = true;//nestedMethod[nestedType] != 0;
+ int variableIndex = variablesCounter[nestedType];
+ int extendedDimension = intStack[intPtr + 1];
+
+ if(isLocalDeclaration || indexOfAssistIdentifier() < 0 || variableIndex != 0 || extendedDimension != 0) {
+ identifierPtr++;
+ identifierLengthPtr++;
+ super.consumeEnterVariable();
+ } else {
+ restartRecovery = AssistParser.STOP_AT_CURSOR;
+
+ // recovery
+ if (currentElement != null) {
+ if(!checkKeyword() && !(currentElement instanceof RecoveredUnit && ((RecoveredUnit)currentElement).statementCount == 0)) {
+ int nameSourceStart = (int)(identifierPositionStack[identifierPtr] >>> 32);
+ intPtr--;
+// pushOnGenericsIdentifiersLengthStack(identifierLengthStack[identifierLengthPtr]);
+// pushOnGenericsLengthStack(0);
+ TypeReference type = getTypeReference(intStack[intPtr--]);
+ intPtr--;
+
+ if (!(currentElement instanceof RecoveredType)
+ && (currentToken == TokenNameDOT
+ || (Util.getLineNumber(type.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
+ != Util.getLineNumber(nameSourceStart, scanner.lineEnds, 0, scanner.linePtr)))){
+ lastCheckPoint = nameSourceStart;
+ restartRecovery = true;
+ return;
+ }
+
+ FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
+ completionFieldDecl.modifiers = intStack[intPtr--];
+ assistNode = completionFieldDecl;
+ lastCheckPoint = type.sourceEnd + 1;
+ currentElement = currentElement.add(completionFieldDecl, 0);
+ lastIgnoredToken = -1;
+ }
+ }
+ }
+}
+protected void consumeEqualityExpression(int op) {
+ super.consumeEqualityExpression(op);
+ popElement(K_BINARY_OPERATOR);
+
+ BinaryExpression exp = (BinaryExpression) expressionStack[expressionPtr];
+ if(assistNode != null && exp.right == assistNode) {
+ assistNodeParent = exp;
+ }
+}
+protected void consumeExitVariableWithInitialization() {
+ super.consumeExitVariableWithInitialization();
+
+ // does not keep the initialization if completion is not inside
+ AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+ if (cursorLocation + 1 < variable.initialization.sourceStart ||
+ cursorLocation > variable.initialization.sourceEnd) {
+ if (STOP_AT_CURSOR)
+ variable.initialization = null;
+ } else if (assistNode != null && assistNode == variable.initialization) {
+ assistNodeParent = variable;
+ }
+}
+protected void consumeCallExpressionWithSimpleName() {
+ this.invocationType = NO_RECEIVER;
+ this.qualifier = -1;
+
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeCallExpressionWithSimpleName();
+ } else {
+ this.pushCompletionOnMemberAccessOnExpressionStack(false);
+ }
+}
+protected void consumeMemberExpressionWithSimpleName() {
+ this.invocationType = NO_RECEIVER;
+ this.qualifier = -1;
+
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeMemberExpressionWithSimpleName();
+ } else {
+ this.pushCompletionOnMemberAccessOnExpressionStack(false);
+ }
+}
+protected void consumeForceNoDiet() {
+ super.consumeForceNoDiet();
+ if (isInsideMethod()) {
+ pushOnElementStack(K_LOCAL_INITIALIZER_DELIMITER);
+ }
+}
+protected void consumeFormalParameter(boolean isVarArgs) {
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeFormalParameter(isVarArgs);
+ } else {
+
+ identifierLengthPtr--;
+ char[] identifierName = identifierStack[identifierPtr];
+ long namePositions = identifierPositionStack[identifierPtr--];
+// int extendedDimensions = this.intStack[this.intPtr--];
+// int endOfEllipsis = 0;
+// if (isVarArgs) {
+// endOfEllipsis = this.intStack[this.intPtr--];
+// }
+// int firstDimensions = this.intStack[this.intPtr--];
+// final int typeDimensions = firstDimensions + extendedDimensions;
+// TypeReference type = getTypeReference(typeDimensions);
+// if (isVarArgs) {
+// type = copyDims(type, typeDimensions + 1);
+// if (extendedDimensions == 0) {
+// type.sourceEnd = endOfEllipsis;
+// }
+// type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+// }
+ intPtr -= 2;
+ CompletionOnArgumentName arg =
+ new CompletionOnArgumentName(
+ identifierName,
+ namePositions,
+ null,
+ intStack[intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers
+ // consume annotations
+// int length;
+// if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+// System.arraycopy(
+// this.expressionStack,
+// (this.expressionPtr -= length) + 1,
+// arg.annotations = new Annotation[length],
+// 0,
+// length);
+// }
+
+ arg.isCatchArgument = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CATCH_AND_RIGHT_PAREN;
+ pushOnAstStack(arg);
+
+ assistNode = arg;
+ this.lastCheckPoint = (int) namePositions;
+ isOrphanCompletionNode = true;
+
+ /* if incomplete method header, listLength counter will not have been reset,
+ indicating that some arguments are available on the stack */
+ listLength++;
+ }
+}
+protected void consumeInsideCastExpression() {
+ int end = intStack[intPtr--];
+ boolean isParameterized =(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_CAST);
+ if(isParameterized) {
+ popElement(K_PARAMETERIZED_CAST);
+
+ if(this.identifierLengthStack[this.identifierLengthPtr] > 0) {
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ }
+ } else {
+ if(this.identifierLengthStack[this.identifierLengthPtr] > 0) {
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+ }
+ }
+ Expression castType = getTypeReference(intStack[intPtr--]);
+ if(isParameterized) {
+ intPtr--;
+ }
+ castType.sourceEnd = end - 1;
+ castType.sourceStart = intStack[intPtr--] + 1;
+ pushOnExpressionStack(castType);
+
+ pushOnElementStack(K_CAST_STATEMENT);
+}
+protected void consumeCallExpressionWithArguments() {
+ popElement(K_SELECTOR_QUALIFIER);
+ popElement(K_SELECTOR_INVOCATION_TYPE);
+ super.consumeCallExpressionWithArguments();
+}
+protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
+ if(this.indexOfAssistIdentifier() < 0) {
+ identifierPtr--;
+ identifierLengthPtr--;
+ if(this.indexOfAssistIdentifier() != 0 ||
+ this.identifierLengthStack[this.identifierLengthPtr] != this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr]) {
+ identifierPtr++;
+ identifierLengthPtr++;
+ super.consumeMethodHeaderName(isAnnotationMethod);
+ } else {
+ restartRecovery = AssistParser.STOP_AT_CURSOR;
+
+ // recovery
+ if (currentElement != null) {
+ //name
+// char[] selector = identifierStack[identifierPtr + 1];
+// long selectorSource = identifierPositionStack[identifierPtr + 1];
+
+// //type
+// TypeReference type = getTypeReference(intStack[intPtr--]);
+// ((CompletionOnSingleTypeReference)type).isCompletionNode = false;
+// //modifiers
+// int declarationSourceStart = intStack[intPtr--];
+// int mod = intStack[intPtr--];
+
+// if(Util.getLineNumber(type.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
+// != Util.getLineNumber((int) (selectorSource >>> 32), scanner.lineEnds, 0, scanner.linePtr)) {
+// FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
+// // consume annotations
+// int length;
+// if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+// System.arraycopy(
+// this.expressionStack,
+// (this.expressionPtr -= length) + 1,
+// completionFieldDecl.annotations = new Annotation[length],
+// 0,
+// length);
+// }
+// completionFieldDecl.modifiers = mod;
+// assistNode = completionFieldDecl;
+// lastCheckPoint = type.sourceEnd + 1;
+// currentElement = currentElement.add(completionFieldDecl, 0);
+// lastIgnoredToken = -1;
+// } else {
+// CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult);
+// // consume annotations
+// int length;
+// if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+// System.arraycopy(
+// this.expressionStack,
+// (this.expressionPtr -= length) + 1,
+// md.annotations = new Annotation[length],
+// 0,
+// length);
+// }
+// md.selector = selector;
+// md.declarationSourceStart = declarationSourceStart;
+// md.modifiers = mod;
+// md.bodyStart = lParenPos+1;
+// listLength = 0; // initialize listLength before reading parameters/throws
+// assistNode = md;
+// this.lastCheckPoint = md.bodyStart;
+// currentElement = currentElement.add(md, 0);
+// lastIgnoredToken = -1;
+// // javadoc
+// md.javadoc = this.javadoc;
+// this.javadoc = null;
+// }
+ }
+ }
+ } else {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ CompletionOnMethodName md = new CompletionOnMethodName(this.compilationUnit.compilationResult);
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ long selectorSource = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+ this.expressionLengthPtr--;
+ // javadoc
+ md.javadoc = this.javadoc;
+ this.javadoc = null;
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSource >>> 32);
+ md.selectorEnd = (int) selectorSource;
+ pushOnAstStack(md);
+ md.sourceEnd = lParenPos;
+ md.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ this.assistNode = md;
+ this.lastCheckPoint = md.sourceEnd;
+ // recovery
+ if (currentElement != null){
+ if (currentElement instanceof RecoveredType
+ //|| md.modifiers != 0
+ || (Util.getLineNumber(md.returnType.sourceStart, scanner.lineEnds, 0, scanner.linePtr)
+ == Util.getLineNumber(md.sourceStart, scanner.lineEnds, 0, scanner.linePtr))){
+ lastCheckPoint = md.bodyStart;
+ currentElement = currentElement.add(md, 0);
+ lastIgnoredToken = -1;
+ } else {
+ lastCheckPoint = md.sourceStart;
+ restartRecovery = AssistParser.STOP_AT_CURSOR;
+ }
+ }
+ }
+}
+protected void consumeMethodHeaderRightParen() {
+ super.consumeMethodHeaderRightParen();
+
+ if (currentElement != null
+ && currentToken == TokenNameIdentifier
+ && this.cursorLocation+1 >= scanner.startPosition
+ && this.cursorLocation < scanner.currentPosition){
+ this.pushIdentifier();
+
+ int index = -1;
+ /* check if current awaiting identifier is the completion identifier */
+ if ((index = this.indexOfAssistIdentifier()) > -1) {
+ int ptr = this.identifierPtr - this.identifierLengthStack[this.identifierLengthPtr] + index + 1;
+ if (currentElement instanceof RecoveredMethod){
+ RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (!recoveredMethod.foundOpeningBrace) {
+ CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
+ identifierStack[ptr],
+ identifierPositionStack[ptr],
+ Keywords.THROWS);
+ recoveredMethod.foundOpeningBrace = true;
+ this.assistNode = completionOnKeyword;
+ this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
+ }
+ }
+ }
+ }
+}
+protected void consumeLabel() {
+ super.consumeLabel();
+ this.pushOnLabelStack(this.identifierStack[this.identifierPtr]);
+ this.pushOnElementStack(K_LABEL, this.labelPtr);
+}
+protected void consumeMethodBody() {
+ popElement(K_BLOCK_DELIMITER);
+ super.consumeMethodBody();
+}
+protected void consumeMethodHeader() {
+ super.consumeMethodHeader();
+ pushOnElementStack(K_BLOCK_DELIMITER);
+}
+protected void consumeRestoreDiet() {
+ super.consumeRestoreDiet();
+ if (isInsideMethod()) {
+ popElement(K_LOCAL_INITIALIZER_DELIMITER);
+ }
+}
+protected void consumeStatementBreakWithLabel() {
+ super.consumeStatementBreakWithLabel();
+ if (this.record) {
+ ASTNode breakStatement = this.astStack[this.astPtr];
+ if (!isAlreadyPotentialName(breakStatement.sourceStart)) {
+ this.addPotentialName(null, breakStatement.sourceStart, breakStatement.sourceEnd);
+ }
+ }
+
+}
+
+protected void consumeStatementLabel() {
+ this.popElement(K_LABEL);
+ super.consumeStatementLabel();
+}
+protected void consumeStatementSwitch() {
+ super.consumeStatementSwitch();
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
+ popElement(K_SWITCH_LABEL);
+ popElement(K_BLOCK_DELIMITER);
+ }
+}
+protected void consumeNestedMethod() {
+ super.consumeNestedMethod();
+ if(!(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER)) pushOnElementStack(K_BLOCK_DELIMITER);
+}
+protected void consumePushPosition() {
+ super.consumePushPosition();
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BINARY_OPERATOR) {
+ int info = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
+ popElement(K_BINARY_OPERATOR);
+ pushOnElementStack(K_UNARY_OPERATOR, info);
+ }
+}
+protected void consumeToken(int token) {
+ if(isFirst) {
+ super.consumeToken(token);
+ return;
+ }
+ if(canBeExplicitConstructor == NEXTTOKEN) {
+ canBeExplicitConstructor = YES;
+ } else {
+ canBeExplicitConstructor = NO;
+ }
+
+ int previous = this.previousToken;
+ int prevIdentifierPtr = this.previousIdentifierPtr;
+
+ if (isInsideMethod() || isInsideFieldInitialization() || isInsideAnnotation()) {
+ switch(token) {
+ case TokenNameLPAREN:
+ if(previous == TokenNameIdentifier &&
+ topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_PARAMETERIZED_METHOD_INVOCATION) {
+ popElement(K_PARAMETERIZED_METHOD_INVOCATION);
+ } else {
+ popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
+ }
+ break;
+ case TokenNameLBRACE:
+ popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
+ break;
+ case TokenNameLBRACKET:
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_NEW_AND_LEFT_BRACKET) {
+ popElement(K_BETWEEN_NEW_AND_LEFT_BRACKET);
+ pushOnElementStack(K_ARRAY_CREATION);
+ }
+ break;
+ case TokenNameRBRACE:
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ switch (kind) {
+ case K_BLOCK_DELIMITER:
+ popElement(K_BLOCK_DELIMITER);
+ break;
+ case K_MEMBER_VALUE_ARRAY_INITIALIZER:
+ popElement(K_MEMBER_VALUE_ARRAY_INITIALIZER);
+ break;
+ default:
+ popElement(K_ARRAY_INITIALIZER);
+ break;
+ }
+ break;
+ case TokenNameRBRACKET:
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_LEFT_AND_RIGHT_BRACKET) {
+ popElement(K_BETWEEN_LEFT_AND_RIGHT_BRACKET);
+ }
+ break;
+
+ }
+ }
+ super.consumeToken(token);
+
+ // if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
+ // then position end of file at cursor location (so that we have the same behavior as
+ // in method bodies)
+ if (token == TokenNameIdentifier
+ && this.identifierStack[this.identifierPtr] == assistIdentifier()
+ && this.currentElement == null
+ && this.isIndirectlyInsideFieldInitialization()) {
+// this.scanner.eofPosition = cursorLocation < Integer.MAX_VALUE ? cursorLocation+1 : cursorLocation;
+ }
+
+ // if in a method or if in a field initializer
+ if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue()) {
+ switch (token) {
+ case TokenNameDOT:
+ switch (previous) {
+ case TokenNamethis: // eg. this[.]fred()
+ this.invocationType = EXPLICIT_RECEIVER;
+ break;
+ case TokenNamesuper: // eg. super[.]fred()
+ this.invocationType = SUPER_RECEIVER;
+ break;
+ case TokenNameIdentifier: // eg. bar[.]fred()
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_BETWEEN_NEW_AND_LEFT_BRACKET) {
+ if (this.identifierPtr != prevIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
+ this.invocationType = EXPLICIT_RECEIVER;
+ } else {
+ this.invocationType = NAME_RECEIVER;
+ }
+ }
+ break;
+ }
+ break;
+ case TokenNameIdentifier:
+ if (previous == TokenNameDOT) { // eg. foo().[fred]()
+ if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
+ && this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
+ && this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
+ && this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
+
+ this.invocationType = EXPLICIT_RECEIVER;
+ this.qualifier = this.expressionPtr;
+ }
+ }
+ break;
+ case TokenNamenew:
+ pushOnElementStack(K_BETWEEN_NEW_AND_LEFT_BRACKET);
+ this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
+ if (previous == TokenNameDOT) { // eg. fred().[new] X()
+ this.invocationType = QUALIFIED_ALLOCATION;
+ } else { // eg. [new] X()
+ this.invocationType = ALLOCATION;
+ }
+ break;
+ case TokenNamethis:
+ if (previous == TokenNameDOT) { // eg. fred().[this]()
+ this.invocationType = QUALIFIED_ALLOCATION;
+ this.qualifier = this.expressionPtr;
+ }
+ break;
+ case TokenNamesuper:
+ if (previous == TokenNameDOT) { // eg. fred().[super]()
+ this.invocationType = QUALIFIED_ALLOCATION;
+ this.qualifier = this.expressionPtr;
+ }
+ break;
+ case TokenNamecatch:
+ pushOnElementStack(K_BETWEEN_CATCH_AND_RIGHT_PAREN);
+ break;
+ case TokenNameLPAREN:
+ if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER || this.invocationType == SUPER_RECEIVER) {
+ this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
+ }
+ switch (previous) {
+ case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
+ int info = 0;
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER,1) == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN &&
+ (info=topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER,1) & LPAREN_NOT_CONSUMED) != 0) {
+ this.popElement(K_SELECTOR);
+ this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
+ if ((info & ANNOTATION_NAME_COMPLETION) != 0) {
+ this.pushOnElementStack(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN, LPAREN_CONSUMED | ANNOTATION_NAME_COMPLETION);
+ } else {
+ this.pushOnElementStack(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN, LPAREN_CONSUMED);
+ } } else {
+ this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, this.invocationType);
+ int selectorQualifier=(this.invocationType==ALLOCATION)?this.expressionPtr:this.qualifier;
+ this.pushOnElementStack(K_SELECTOR_QUALIFIER, selectorQualifier);
+ }
+ }
+ this.qualifier = -1;
+ this.invocationType = NO_RECEIVER;
+ break;
+ case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
+ this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
+ this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
+ }
+ this.qualifier = -1;
+ this.invocationType = NO_RECEIVER;
+ break;
+ case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
+ this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
+ this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
+ }
+ this.qualifier = -1;
+ this.invocationType = NO_RECEIVER;
+ break;
+ case TokenNameGREATER: // explicit constructor invocation, eg. Fred[(]1, 2)
+ case TokenNameRIGHT_SHIFT: // or fred>[(]1, 2)
+ case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred>>[(]1, 2)
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SELECTOR) {
+ if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, 1) == K_BINARY_OPERATOR &&
+ topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1) == GREATER) {
+ // it's not a selector invocation
+ popElement(K_SELECTOR);
+ } else {
+ this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
+ this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
+ }
+ }
+ this.qualifier = -1;
+ this.invocationType = NO_RECEIVER;
+ break;
+ }
+ break;
+ case TokenNameLBRACE:
+ this.bracketDepth++;
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ if(kind == K_FIELD_INITIALIZER_DELIMITER
+ || kind == K_LOCAL_INITIALIZER_DELIMITER
+ || kind == K_ARRAY_CREATION) {
+ pushOnElementStack(K_ARRAY_INITIALIZER, endPosition);
+ } else if (kind == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN) {
+ pushOnElementStack(K_MEMBER_VALUE_ARRAY_INITIALIZER, endPosition);
+ } else {
+ switch(previous) {
+ case TokenNameRPAREN :
+ switch(previousKind) {
+ case K_BETWEEN_IF_AND_RIGHT_PAREN :
+ pushOnElementStack(K_BLOCK_DELIMITER, IF);
+ break;
+ case K_BETWEEN_CATCH_AND_RIGHT_PAREN :
+ pushOnElementStack(K_BLOCK_DELIMITER, CATCH);
+ break;
+ case K_BETWEEN_WHILE_AND_RIGHT_PAREN :
+ pushOnElementStack(K_BLOCK_DELIMITER, WHILE);
+ break;
+ case K_BETWEEN_SWITCH_AND_RIGHT_PAREN :
+ pushOnElementStack(K_BLOCK_DELIMITER, SWITCH);
+ break;
+ case K_BETWEEN_FOR_AND_RIGHT_PAREN :
+ pushOnElementStack(K_BLOCK_DELIMITER, FOR);
+ break;
+ case K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN :
+ pushOnElementStack(K_BLOCK_DELIMITER, SYNCHRONIZED);
+ break;
+ default :
+ pushOnElementStack(K_BLOCK_DELIMITER);
+ break;
+ }
+ break;
+ case TokenNametry :
+ pushOnElementStack(K_BLOCK_DELIMITER, TRY);
+ break;
+ case TokenNamedo:
+ pushOnElementStack(K_BLOCK_DELIMITER, DO);
+ break;
+ default :
+ pushOnElementStack(K_BLOCK_DELIMITER);
+ break;
+ }
+ }
+ break;
+ case TokenNameLBRACKET:
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_ARRAY_CREATION) {
+ pushOnElementStack(K_BETWEEN_LEFT_AND_RIGHT_BRACKET);
+ } else {
+ if(previous == TokenNameIdentifier) {
+ invocationType = NO_RECEIVER;
+ qualifier = -1;
+ }
+ }
+ this.bracketDepth++;
+ break;
+ case TokenNameRBRACE:
+ this.bracketDepth--;
+ break;
+ case TokenNameRBRACKET:
+ this.bracketDepth--;
+ break;
+ case TokenNameRPAREN:
+ switch(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
+ case K_BETWEEN_CATCH_AND_RIGHT_PAREN :
+ popElement(K_BETWEEN_CATCH_AND_RIGHT_PAREN);
+ break;
+ case K_BETWEEN_IF_AND_RIGHT_PAREN :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
+ popElement(K_BETWEEN_IF_AND_RIGHT_PAREN);
+ }
+ break;
+ case K_BETWEEN_WHILE_AND_RIGHT_PAREN :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
+ popElement(K_BETWEEN_WHILE_AND_RIGHT_PAREN);
+ }
+ break;
+ case K_BETWEEN_FOR_AND_RIGHT_PAREN :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
+ popElement(K_BETWEEN_FOR_AND_RIGHT_PAREN);
+ }
+ break;
+ case K_BETWEEN_SWITCH_AND_RIGHT_PAREN :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
+ popElement(K_BETWEEN_SWITCH_AND_RIGHT_PAREN);
+ }
+ break;
+ case K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == bracketDepth) {
+ popElement(K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN);
+ }
+ break;
+ }
+ break;
+ case TokenNamethrow:
+ pushOnElementStack(K_INSIDE_THROW_STATEMENT, bracketDepth);
+ break;
+ case TokenNameSEMICOLON:
+ switch(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
+ case K_INSIDE_THROW_STATEMENT :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+ popElement(K_INSIDE_THROW_STATEMENT);
+ }
+ break;
+ case K_INSIDE_RETURN_STATEMENT :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+ popElement(K_INSIDE_RETURN_STATEMENT);
+ }
+ break;
+ case K_INSIDE_ASSERT_STATEMENT :
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+ popElement(K_INSIDE_ASSERT_STATEMENT);
+ }
+ break;
+ case K_INSIDE_BREAK_STATEMENT:
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+ popElement(K_INSIDE_BREAK_STATEMENT);
+ }
+ break;
+ case K_INSIDE_CONTINUE_STATEMENT:
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+ popElement(K_INSIDE_CONTINUE_STATEMENT);
+ }
+ break;
+ }
+ break;
+ case TokenNamereturn:
+ pushOnElementStack(K_INSIDE_RETURN_STATEMENT, this.bracketDepth);
+ break;
+ case TokenNameMULTIPLY:
+ pushOnElementStack(K_BINARY_OPERATOR, MULTIPLY);
+ break;
+ case TokenNameDIVIDE:
+ pushOnElementStack(K_BINARY_OPERATOR, DIVIDE);
+ break;
+ case TokenNameREMAINDER:
+ pushOnElementStack(K_BINARY_OPERATOR, REMAINDER);
+ break;
+ case TokenNamePLUS:
+ pushOnElementStack(K_BINARY_OPERATOR, PLUS);
+ break;
+ case TokenNameMINUS:
+ pushOnElementStack(K_BINARY_OPERATOR, MINUS);
+ break;
+ case TokenNameLEFT_SHIFT:
+ pushOnElementStack(K_BINARY_OPERATOR, LEFT_SHIFT);
+ break;
+ case TokenNameRIGHT_SHIFT:
+ pushOnElementStack(K_BINARY_OPERATOR, RIGHT_SHIFT);
+ break;
+ case TokenNameUNSIGNED_RIGHT_SHIFT:
+ pushOnElementStack(K_BINARY_OPERATOR, UNSIGNED_RIGHT_SHIFT);
+ break;
+ case TokenNameLESS:
+ switch(previous) {
+ case TokenNameDOT :
+ pushOnElementStack(K_PARAMETERIZED_METHOD_INVOCATION);
+ break;
+ case TokenNamenew :
+ pushOnElementStack(K_PARAMETERIZED_ALLOCATION);
+ break;
+ }
+ pushOnElementStack(K_BINARY_OPERATOR, LESS);
+ break;
+ case TokenNameGREATER:
+ pushOnElementStack(K_BINARY_OPERATOR, GREATER);
+ break;
+ case TokenNameLESS_EQUAL:
+ pushOnElementStack(K_BINARY_OPERATOR, LESS_EQUAL);
+ break;
+ case TokenNameGREATER_EQUAL:
+ pushOnElementStack(K_BINARY_OPERATOR, GREATER_EQUAL);
+ break;
+ case TokenNameAND:
+ pushOnElementStack(K_BINARY_OPERATOR, AND);
+ break;
+ case TokenNameXOR:
+ pushOnElementStack(K_BINARY_OPERATOR, XOR);
+ break;
+ case TokenNameOR:
+ pushOnElementStack(K_BINARY_OPERATOR, OR);
+ break;
+ case TokenNameAND_AND:
+ pushOnElementStack(K_BINARY_OPERATOR, AND_AND);
+ break;
+ case TokenNameOR_OR:
+ pushOnElementStack(K_BINARY_OPERATOR, OR_OR);
+ break;
+ case TokenNamePLUS_PLUS:
+ pushOnElementStack(K_UNARY_OPERATOR, PLUS_PLUS);
+ break;
+ case TokenNameMINUS_MINUS:
+ pushOnElementStack(K_UNARY_OPERATOR, MINUS_MINUS);
+ break;
+ case TokenNameTWIDDLE:
+ pushOnElementStack(K_UNARY_OPERATOR, TWIDDLE);
+ break;
+ case TokenNameNOT:
+ pushOnElementStack(K_UNARY_OPERATOR, NOT);
+ break;
+ case TokenNameEQUAL_EQUAL:
+ pushOnElementStack(K_BINARY_OPERATOR, EQUAL_EQUAL);
+ break;
+ case TokenNameNOT_EQUAL:
+ pushOnElementStack(K_BINARY_OPERATOR, NOT_EQUAL);
+ break;
+ case TokenNameinstanceof:
+ pushOnElementStack(K_BINARY_OPERATOR, INSTANCEOF);
+ break;
+ case TokenNameQUESTION:
+ if(previous != TokenNameLESS) {
+ pushOnElementStack(K_CONDITIONAL_OPERATOR, QUESTION);
+ }
+ break;
+ case TokenNameCOLON:
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_CONDITIONAL_OPERATOR
+ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == QUESTION) {
+ popElement(K_CONDITIONAL_OPERATOR);
+ pushOnElementStack(K_CONDITIONAL_OPERATOR, COLON);
+ } else {
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BETWEEN_CASE_AND_COLON) {
+ popElement(K_BETWEEN_CASE_AND_COLON);
+ } else {
+ popElement(K_BETWEEN_DEFAULT_AND_COLON);
+ }
+ }
+ break;
+ case TokenNameif:
+ pushOnElementStack(K_BETWEEN_IF_AND_RIGHT_PAREN, bracketDepth);
+ break;
+ case TokenNamewhile:
+ pushOnElementStack(K_BETWEEN_WHILE_AND_RIGHT_PAREN, bracketDepth);
+ break;
+ case TokenNamefor:
+ pushOnElementStack(K_BETWEEN_FOR_AND_RIGHT_PAREN, bracketDepth);
+ break;
+ case TokenNameswitch:
+ pushOnElementStack(K_BETWEEN_SWITCH_AND_RIGHT_PAREN, bracketDepth);
+ break;
+ case TokenNamesynchronized:
+ pushOnElementStack(K_BETWEEN_SYNCHRONIZED_AND_RIGHT_PAREN, bracketDepth);
+ break;
+// case TokenNameassert:
+// pushOnElementStack(K_INSIDE_ASSERT_STATEMENT, this.bracketDepth);
+// break;
+ case TokenNamecase :
+ pushOnElementStack(K_BETWEEN_CASE_AND_COLON);
+ break;
+ case TokenNamedefault :
+ pushOnElementStack(K_BETWEEN_DEFAULT_AND_COLON);
+ break;
+ case TokenNameextends:
+ pushOnElementStack(K_EXTENDS_KEYWORD);
+ break;
+ case TokenNamebreak:
+ pushOnElementStack(K_INSIDE_BREAK_STATEMENT, bracketDepth);
+ break;
+ case TokenNamecontinue:
+ pushOnElementStack(K_INSIDE_CONTINUE_STATEMENT, bracketDepth);
+ break;
+ }
+ } else {
+ switch(token) {
+ case TokenNameextends:
+ pushOnElementStack(K_EXTENDS_KEYWORD);
+ break;
+ case TokenNameLESS:
+ pushOnElementStack(K_BINARY_OPERATOR, LESS);
+ break;
+ case TokenNameGREATER:
+ pushOnElementStack(K_BINARY_OPERATOR, GREATER);
+ break;
+ case TokenNameRIGHT_SHIFT:
+ pushOnElementStack(K_BINARY_OPERATOR, RIGHT_SHIFT);
+ break;
+ case TokenNameUNSIGNED_RIGHT_SHIFT:
+ pushOnElementStack(K_BINARY_OPERATOR, UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ }
+ }
+}
+protected void consumeRightParen() {
+ super.consumeRightParen();
+}
+protected void consumeUnaryExpression(int op) {
+ super.consumeUnaryExpression(op);
+ popElement(K_UNARY_OPERATOR);
+
+ if(expressionStack[expressionPtr] instanceof UnaryExpression) {
+ UnaryExpression exp = (UnaryExpression) expressionStack[expressionPtr];
+ if(assistNode != null && exp.expression == assistNode) {
+ assistNodeParent = exp;
+ }
+ }
+}
+protected void consumeUnaryExpression(int op, boolean post) {
+ super.consumeUnaryExpression(op, post);
+ popElement(K_UNARY_OPERATOR);
+
+ if(expressionStack[expressionPtr] instanceof UnaryExpression) {
+ UnaryExpression exp = (UnaryExpression) expressionStack[expressionPtr];
+ if(assistNode != null && exp.expression == assistNode) {
+ assistNodeParent = exp;
+ }
+ }
+}
+
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+ return new CompletionOnImportReference(tokens, positions);
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
+ return new CompletionOnQualifiedNameReference(
+ previousIdentifiers,
+ assistName,
+ positions,
+ isInsideAttributeValue());
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
+ switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
+ case K_NEXT_TYPEREF_IS_EXCEPTION :
+ return new CompletionOnQualifiedTypeReference(
+ previousIdentifiers,
+ assistName,
+ positions,
+ CompletionOnQualifiedTypeReference.K_EXCEPTION);
+ case K_NEXT_TYPEREF_IS_CLASS :
+ return new CompletionOnQualifiedTypeReference(
+ previousIdentifiers,
+ assistName,
+ positions,
+ CompletionOnQualifiedTypeReference.K_CLASS);
+ case K_NEXT_TYPEREF_IS_INTERFACE :
+ return new CompletionOnQualifiedTypeReference(
+ previousIdentifiers,
+ assistName,
+ positions,
+ CompletionOnQualifiedTypeReference.K_INTERFACE);
+ default :
+ return new CompletionOnQualifiedTypeReference(
+ previousIdentifiers,
+ assistName,
+ positions);
+ }
+}
+public NameReference createSingleAssistNameReference(char[] assistName, long position) {
+ int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+ if(false){//!isInsideMethod()) {
+ if (isInsideFieldInitialization()) {
+ return new CompletionOnSingleNameReference(
+ assistName,
+ position,
+ new char[][]{Keywords.FALSE, Keywords.TRUE},
+ false,
+ isInsideAttributeValue());
+ }
+ return new CompletionOnSingleNameReference(assistName, position, isInsideAttributeValue());
+ } else {
+ boolean canBeExplicitConstructorCall = false;
+ if(kind == K_BLOCK_DELIMITER
+ && previousKind == K_BLOCK_DELIMITER
+ && previousInfo == DO) {
+ return new CompletionOnKeyword3(assistName, position, Keywords.WHILE);
+ } else if(kind == K_BLOCK_DELIMITER
+ && previousKind == K_BLOCK_DELIMITER
+ && previousInfo == TRY) {
+ return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CATCH, Keywords.FINALLY});
+ } else if(kind == K_BLOCK_DELIMITER
+ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
+ return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CASE, Keywords.DEFAULT});
+ } else {
+ char[][] keywords = new char[Keywords.COUNT][];
+ int count = 0;
+
+// if((lastModifiers & ClassFileConstants.AccStatic) == 0) {
+// keywords[count++]= Keywords.SUPER;
+ keywords[count++]= Keywords.THIS;
+// }
+ keywords[count++]= Keywords.NEW;
+
+ if(kind == K_BLOCK_DELIMITER || kind==0) {
+ if(canBeExplicitConstructor == YES) {
+ canBeExplicitConstructorCall = true;
+ }
+
+// keywords[count++]= Keywords.ASSERT;
+ keywords[count++]= Keywords.DO;
+ keywords[count++]= Keywords.FOR;
+ keywords[count++]= Keywords.IF;
+ keywords[count++]= Keywords.RETURN;
+ keywords[count++]= Keywords.SWITCH;
+// keywords[count++]= Keywords.SYNCHRONIZED;
+ keywords[count++]= Keywords.THROW;
+ keywords[count++]= Keywords.TRY;
+ keywords[count++]= Keywords.WHILE;
+ keywords[count++]= Keywords.VAR;
+ keywords[count++]= Keywords.FUNCTION;
+ keywords[count++]= Keywords.DELETE;
+ keywords[count++]= Keywords.TYPEOF;
+
+// keywords[count++]= Keywords.FINAL;
+// keywords[count++]= Keywords.CLASS;
+
+ if(previousKind == K_BLOCK_DELIMITER) {
+ switch (previousInfo) {
+ case IF :
+ keywords[count++]= Keywords.ELSE;
+ break;
+ case CATCH :
+ keywords[count++]= Keywords.CATCH;
+ keywords[count++]= Keywords.FINALLY;
+ break;
+ }
+ }
+ if(isInsideLoop()) {
+ keywords[count++]= Keywords.CONTINUE;
+ }
+ if(isInsideBreakable()) {
+ keywords[count++]= Keywords.BREAK;
+ }
+ } else if(kind != K_BETWEEN_CASE_AND_COLON && kind != K_BETWEEN_DEFAULT_AND_COLON) {
+ keywords[count++]= Keywords.TRUE;
+ keywords[count++]= Keywords.FALSE;
+ keywords[count++]= Keywords.NULL;
+ keywords[count++]= Keywords.UNDEFINED;
+ keywords[count++]= Keywords.FUNCTION;
+
+ if(kind == K_SWITCH_LABEL) {
+ if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) != DEFAULT) {
+ keywords[count++]= Keywords.DEFAULT;
+ }
+ keywords[count++]= Keywords.BREAK;
+ keywords[count++]= Keywords.CASE;
+ keywords[count++]= Keywords.DO;
+ keywords[count++]= Keywords.FOR;
+ keywords[count++]= Keywords.IF;
+ keywords[count++]= Keywords.RETURN;
+ keywords[count++]= Keywords.SWITCH;
+// keywords[count++]= Keywords.SYNCHRONIZED;
+ keywords[count++]= Keywords.THROW;
+ keywords[count++]= Keywords.TRY;
+ keywords[count++]= Keywords.WHILE;
+ keywords[count++]= Keywords.VAR;
+ keywords[count++]= Keywords.FUNCTION;
+ keywords[count++]= Keywords.DELETE;
+ keywords[count++]= Keywords.TYPEOF;
+ if(isInsideLoop()) {
+ keywords[count++]= Keywords.CONTINUE;
+ } }
+ }
+ System.arraycopy(keywords, 0 , keywords = new char[count][], 0, count);
+
+ return new CompletionOnSingleNameReference(assistName, position, keywords, canBeExplicitConstructorCall, isInsideAttributeValue());
+ }
+ }
+}
+public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
+ switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
+ case K_NEXT_TYPEREF_IS_EXCEPTION :
+ return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_EXCEPTION) ;
+ case K_NEXT_TYPEREF_IS_CLASS :
+ return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_CLASS);
+ case K_NEXT_TYPEREF_IS_INTERFACE :
+ return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_INTERFACE);
+ default :
+ return new CompletionOnSingleTypeReference(assistName, position);
+ }
+}
+public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
+ return this.createSingleAssistTypeReference(assistName, position);
+}
+protected StringLiteral createStringLiteral(char[] token, int start, int end, int lineNumber) {
+ if (start <= this.cursorLocation && this.cursorLocation <= end){
+ char[] source = this.scanner.source;
+
+ int contentStart = start;
+ int contentEnd = end;
+
+ // " could be as unicode \u0022
+ int pos = contentStart;
+ if(source[pos] == '\"') {
+ contentStart = pos + 1;
+ } else if(source[pos] == '\\' && source[pos+1] == 'u') {
+ pos += 2;
+ while (source[pos] == 'u') {
+ pos++;
+ }
+ if(source[pos] == 0 && source[pos + 1] == 0 && source[pos + 2] == 2 && source[pos + 3] == 2) {
+ contentStart = pos + 4;
+ }
+ }
+
+ pos = contentEnd;
+ if(source[pos] == '\"') {
+ contentEnd = pos - 1;
+ } else if(source.length > 5 && source[pos-4] == 'u') {
+ if(source[pos - 3] == 0 && source[pos - 2] == 0 && source[pos - 1] == 2 && source[pos] == 2) {
+ pos -= 5;
+ while (pos > -1 && source[pos] == 'u') {
+ pos--;
+ }
+ if(pos > -1 && source[pos] == '\\') {
+ contentEnd = pos - 1;
+ }
+ }
+ }
+
+ if(contentEnd < start) {
+ contentEnd = end;
+ }
+
+ if(this.cursorLocation != end || end == contentEnd) {
+ CompletionOnStringLiteral stringLiteral = new CompletionOnStringLiteral(
+ token,
+ start,
+ end,
+ contentStart,
+ contentEnd,
+ lineNumber);
+
+ this.assistNode = stringLiteral;
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR;
+ this.lastCheckPoint = end;
+
+ return stringLiteral;
+ }
+ }
+ return super.createStringLiteral(token, start, end, lineNumber);
+}
+protected TypeReference copyDims(TypeReference typeRef, int dim) {
+ if (this.assistNode == typeRef) {
+ return typeRef;
+ }
+ TypeReference result = super.copyDims(typeRef, dim);
+ if (this.assistNodeParent == typeRef) {
+ this.assistNodeParent = result;
+ }
+ return result;
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
+
+ this.cursorLocation = cursorLoc;
+ CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+ completionScanner.completionIdentifier = null;
+ completionScanner.cursorLocation = cursorLoc;
+ return this.dietParse(sourceUnit, compilationResult);
+}
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState() {
+
+ super.flushAssistState();
+ this.isOrphanCompletionNode = false;
+ this.isAlreadyAttached = false;
+ assistNodeParent = null;
+ CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+ completionScanner.completedIdentifierStart = 0;
+ completionScanner.completedIdentifierEnd = -1;
+}
+protected NameReference getUnspecifiedReference() {
+ NameReference nameReference = super.getUnspecifiedReference();
+ if (this.record) {
+ recordReference(nameReference);
+ }
+ return nameReference;
+}
+protected NameReference getUnspecifiedReferenceOptimized() {
+ if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
+ // potential receiver is being poped, so reset potential receiver
+ this.invocationType = NO_RECEIVER;
+ this.qualifier = -1;
+ }
+ NameReference nameReference = super.getUnspecifiedReferenceOptimized();
+ if (this.record) {
+ recordReference(nameReference);
+ }
+ return nameReference;
+}
+private boolean isAlreadyPotentialName(int identifierStart) {
+ if (this.potentialVariableNamesPtr < 0) return false;
+
+ return identifierStart <= this.potentialVariableNameEnds[this.potentialVariableNamesPtr];
+}
+protected int indexOfAssistIdentifier(boolean useGenericsStack) {
+ if (this.record) return -1; // when names are recorded there is no assist identifier
+ return super.indexOfAssistIdentifier(useGenericsStack);
+}
+public void initialize() {
+ super.initialize();
+ this.labelPtr = -1;
+ this.initializeForBlockStatements();
+}
+public void initialize(boolean initializeNLS) {
+ super.initialize(initializeNLS);
+ this.labelPtr = -1;
+ this.initializeForBlockStatements();
+}
+/*
+ * Initializes the state of the parser that is about to go for BlockStatements.
+ */
+private void initializeForBlockStatements() {
+ this.previousToken = -1;
+ this.previousIdentifierPtr = -1;
+ this.bracketDepth = 0;
+ this.invocationType = NO_RECEIVER;
+ this.qualifier = -1;
+ popUntilElement(K_SWITCH_LABEL);
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_SWITCH_LABEL) {
+ this.popUntilElement(K_BLOCK_DELIMITER);
+ }
+}
+public void initializeScanner(){
+ this.scanner = new CompletionScanner(this.options.sourceLevel);
+}
+/**
+ * Returns whether the completion is just after an array type
+ * eg. String[].[cursor]
+ */
+private boolean isAfterArrayType() {
+ // TBD: The following relies on the fact that array dimensions are small: it says that if the
+ // top of the intStack is less than 11, then it must be a dimension
+ // (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
+ if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
+ return true;
+ }
+ return false;
+}
+private boolean isEmptyNameCompletion() {
+ return
+ this.assistNode != null &&
+ this.assistNode instanceof CompletionOnSingleNameReference &&
+ (((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
+}
+protected boolean isInsideAnnotation() {
+ int i = elementPtr;
+ while(i > -1) {
+ if(elementKindStack[i] == K_BETWEEN_ANNOTATION_NAME_AND_RPAREN)
+ return true;
+ i--;
+ }
+ return false;
+}
+protected boolean isIndirectlyInsideBlock(){
+ int i = elementPtr;
+ while(i > -1) {
+ if(elementKindStack[i] == K_BLOCK_DELIMITER)
+ return true;
+ i--;
+ }
+ return false;
+}
+
+protected boolean isInsideBlock(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ case K_BLOCK_DELIMITER : return true;
+ }
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideBreakable(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ case K_SWITCH_LABEL : return true;
+ case K_BLOCK_DELIMITER :
+ switch(elementInfoStack[i]) {
+ case FOR :
+ case DO :
+ case WHILE :
+ return true;
+ }
+ }
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideLoop(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ case K_BLOCK_DELIMITER :
+ switch(elementInfoStack[i]) {
+ case FOR :
+ case DO :
+ case WHILE :
+ return true;
+ }
+ }
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideReturn(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ case K_BLOCK_DELIMITER : return false;
+ case K_INSIDE_RETURN_STATEMENT : return true;
+ }
+ i--;
+ }
+ return false;
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
+
+ this.cursorLocation = cursorLoc;
+ CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+ completionScanner.completionIdentifier = null;
+ completionScanner.cursorLocation = cursorLoc;
+ return this.parse(sourceUnit, compilationResult);
+}
+public void parseBlockStatements(
+ ConstructorDeclaration cd,
+ CompilationUnitDeclaration unit) {
+ canBeExplicitConstructor = 1;
+ super.parseBlockStatements(cd, unit);
+}
+public MethodDeclaration parseSomeStatements(int start, int end, int fakeBlocksCount, CompilationUnitDeclaration unit) {
+ this.methodRecoveryActivated = true;
+
+ initialize();
+
+ // simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
+ goForBlockStatementsopt();
+
+ MethodDeclaration fakeMethod = new MethodDeclaration(unit.compilationResult());
+ fakeMethod.selector = FAKE_METHOD_NAME;
+ fakeMethod.bodyStart = start;
+ fakeMethod.bodyEnd = end;
+ fakeMethod.declarationSourceStart = start;
+ fakeMethod.declarationSourceEnd = end;
+ fakeMethod.sourceStart = start;
+ fakeMethod.sourceEnd = start; //fake method must ignore the method header
+
+ referenceContext = fakeMethod;
+ compilationUnit = unit;
+ this.diet = false;
+ this.restartRecovery = true;
+
+
+ scanner.resetTo(start, end);
+ consumeNestedMethod();
+ for (int i = 0; i < fakeBlocksCount; i++) {
+ consumeOpenFakeBlock();
+ }
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ } finally {
+ nestedMethod[nestedType]--;
+ }
+ if (!this.hasError) {
+ int length;
+ if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.astStack,
+ (this.astPtr -= length) + 1,
+ fakeMethod.statements = new Statement[length],
+ 0,
+ length);
+ }
+ }
+
+ return fakeMethod;
+}
+protected void popUntilCompletedAnnotationIfNecessary() {
+ if(elementPtr < 0) return;
+
+ int i = elementPtr;
+ while(i > -1 &&
+ (elementKindStack[i] != K_BETWEEN_ANNOTATION_NAME_AND_RPAREN ||
+ (elementInfoStack[i] & ANNOTATION_NAME_COMPLETION) == 0)) {
+ i--;
+ }
+
+ if(i >= 0) {
+ previousKind = elementKindStack[i];
+ previousInfo = elementInfoStack[i];
+ elementPtr = i - 1;
+ }
+}
+
+/*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+protected void prepareForBlockStatements() {
+ this.nestedMethod[this.nestedType = 0] = 1;
+ this.variablesCounter[this.nestedType] = 0;
+ this.realBlockStack[this.realBlockPtr = 1] = 0;
+
+ this.initializeForBlockStatements();
+}
+protected void pushOnLabelStack(char[] label){
+ if (this.labelPtr < -1) return;
+
+ int stackLength = this.labelStack.length;
+ if (++this.labelPtr >= stackLength) {
+ System.arraycopy(
+ this.labelStack, 0,
+ this.labelStack = new char[stackLength + LabelStackIncrement][], 0,
+ stackLength);
+ }
+ this.labelStack[this.labelPtr] = label;
+}
+/**
+ * Creates a completion on member access node and push it
+ * on the expression stack.
+ */
+private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
+ char[] source = identifierStack[identifierPtr];
+ long pos = identifierPositionStack[identifierPtr--];
+ CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos, isInsideAnnotation());
+ this.assistNode = fr;
+ this.lastCheckPoint = fr.sourceEnd + 1;
+ identifierLengthPtr--;
+ if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....
+ fr.sourceStart = intStack[intPtr--];
+ fr.receiver = new SuperReference(fr.sourceStart, endPosition);
+ pushOnExpressionStack(fr);
+ } else { //optimize push/pop
+ if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
+ fr.sourceStart = fr.receiver.sourceStart;
+ }
+ expressionStack[expressionPtr] = fr;
+ }
+}
+public void recordCompletionOnReference(){
+
+ if (currentElement instanceof RecoveredType){
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+
+ /* filter out cases where scanner is still inside type header */
+ if (!recoveredType.foundOpeningBrace) return;
+
+ /* generate a pseudo field with a completion on type reference */
+ currentElement.add(
+ new CompletionOnFieldType(this.getTypeReference(0), false), 0);
+ return;
+ }
+ if (!diet) return; // only record references attached to types
+
+}
+private void recordReference(NameReference nameReference) {
+ if (!this.skipRecord &&
+ this.recordFrom <= nameReference.sourceStart &&
+ nameReference.sourceEnd <= this.recordTo &&
+ !isAlreadyPotentialName(nameReference.sourceStart)) {
+ char[] token;
+ if (nameReference instanceof SingleNameReference) {
+ token = ((SingleNameReference) nameReference).token;
+ } else {
+ token = ((QualifiedNameReference) nameReference).tokens[0];
+ }
+
+ // Most of the time a name which start with an uppercase is a type name.
+ // As we don't want to resolve names to avoid to slow down performances then this name will be ignored
+ if (Character.isUpperCase(token[0])) return;
+
+ addPotentialName(token, nameReference.sourceStart, nameReference.sourceEnd);
+ }
+}
+public void recoveryExitFromVariable() {
+ if(currentElement != null && currentElement instanceof RecoveredLocalVariable) {
+ RecoveredElement oldElement = currentElement;
+ super.recoveryExitFromVariable();
+ if(oldElement != currentElement) {
+ popElement(K_LOCAL_INITIALIZER_DELIMITER);
+ }
+ } else {
+ super.recoveryExitFromVariable();
+ }
+}
+public void recoveryTokenCheck() {
+ RecoveredElement oldElement = currentElement;
+ switch (currentToken) {
+ case TokenNameLBRACE :
+ super.recoveryTokenCheck();
+ break;
+ case TokenNameRBRACE :
+ super.recoveryTokenCheck();
+ if(currentElement != oldElement && oldElement instanceof RecoveredBlock) {
+ popElement(K_BLOCK_DELIMITER);
+ }
+ break;
+ case TokenNamecase :
+ super.recoveryTokenCheck();
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER
+ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
+ pushOnElementStack(K_SWITCH_LABEL);
+ }
+ break;
+ case TokenNamedefault :
+ super.recoveryTokenCheck();
+ if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER
+ && topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
+ pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
+ } else if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
+ popElement(K_SWITCH_LABEL);
+ pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
+ }
+ break;
+ default :
+ super.recoveryTokenCheck();
+ break;
+ }
+}
+/*
+ * Reset internal state after completion is over
+ */
+
+public void reset() {
+ super.reset();
+ this.cursorLocation = 0;
+}
+/*
+ * Reset internal state after completion is over
+ */
+
+public void resetAfterCompletion() {
+ this.cursorLocation = 0;
+ this.flushAssistState();
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+ if (this.assistNode != null) {
+ /* if reached [eof] inside method body, but still inside nested type,
+ or inside a field initializer, should continue in diet mode until
+ the end of the method body or compilation unit */
+ if ((scanner.eofPosition == cursorLocation+1)
+ && (!(referenceContext instanceof CompilationUnitDeclaration)
+ || isIndirectlyInsideFieldInitialization()
+ || assistNodeParent instanceof FieldDeclaration && !(assistNodeParent instanceof Initializer))) {
+
+ /* disabled since does not handle possible field/message refs, that is, Obj[ASSIST HERE]ect.registerNatives()
+ // consume extra tokens which were part of the qualified reference
+ // so that the replaced source comprises them as well
+ if (this.assistNode instanceof NameReference){
+ int oldEof = scanner.eofPosition;
+ scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
+ scanner.currentPosition = this.cursorLocation+1;
+ int token = -1;
+ try {
+ do {
+ // first token might not have to be a dot
+ if (token >= 0 || !this.completionBehindDot){
+ if ((token = scanner.getNextToken()) != TokenNameDOT) break;
+ }
+ if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
+ this.assistNode.sourceEnd = scanner.currentPosition - 1;
+ } while (token != TokenNameEOF);
+ } catch (InvalidInputException e){
+ } finally {
+ scanner.eofPosition = oldEof;
+ }
+ }
+ */
+ /* restart in diet mode for finding sibling constructs */
+ if (currentElement instanceof RecoveredType
+ || currentElement.enclosingType() != null){
+
+ if(lastCheckPoint <= this.assistNode.sourceEnd) {
+ lastCheckPoint = this.assistNode.sourceEnd+1;
+ }
+ int end = currentElement.topElement().sourceEnd();
+ scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
+ } else {
+ this.resetStacks();
+ return false;
+ }
+ }
+ }
+ return super.resumeAfterRecovery();
+}
+public void setAssistIdentifier(char[] assistIdent){
+ ((CompletionScanner)scanner).completionIdentifier = assistIdent;
+}
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("elementKindStack : int[] = {"); //$NON-NLS-1$
+ for (int i = 0; i <= elementPtr; i++) {
+ buffer.append(String.valueOf(elementKindStack[i])).append(',');
+ }
+ buffer.append("}\n"); //$NON-NLS-1$
+ buffer.append("elementInfoStack : int[] = {"); //$NON-NLS-1$
+ for (int i = 0; i <= elementPtr; i++) {
+ buffer.append(String.valueOf(elementInfoStack[i])).append(',');
+ }
+ buffer.append("}\n"); //$NON-NLS-1$
+ buffer.append(super.toString());
+ return String.valueOf(buffer);
+}
+
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+ /* expose parser state to recovery state */
+ currentElement.updateFromParserState();
+
+ /* may be able to retrieve completionNode as an orphan, and then attach it */
+ this.completionIdentifierCheck();
+ this.attachOrphanCompletionNode();
+
+ // if an assist node has been found and a recovered element exists,
+ // mark enclosing blocks as to be preserved
+ if (this.assistNode != null && this.currentElement != null) {
+ currentElement.preserveEnclosingBlocks();
+ }
+
+ /* check and update recovered state based on current token,
+ this action is also performed when shifting token after recovery
+ got activated once.
+ */
+ this.recoveryTokenCheck();
+
+ this.recoveryExitFromVariable();
+}
+
+protected LocalDeclaration createLocalDeclaration(char[] assistName, int sourceStart, int sourceEnd) {
+ if (this.indexOfAssistIdentifier() < 0) {
+ return super.createLocalDeclaration(assistName, sourceStart, sourceEnd);
+ } else {
+ CompletionOnLocalName local = new CompletionOnLocalName(assistName, sourceStart, sourceEnd);
+ this.assistNode = local;
+ this.lastCheckPoint = sourceEnd + 1;
+ return local;
+ }
+}
+
+protected FieldDeclaration createFieldDeclaration(char[] assistName, int sourceStart, int sourceEnd) {
+ if (this.indexOfAssistIdentifier() < 0 || (currentElement instanceof RecoveredUnit && ((RecoveredUnit)currentElement).statementCount == 0)) {
+ return super.createFieldDeclaration(assistName, sourceStart, sourceEnd);
+ } else {
+ CompletionOnFieldName field = new CompletionOnFieldName(assistName, sourceStart, sourceEnd);
+ this.assistNode = field;
+ this.lastCheckPoint = sourceEnd + 1;
+ return field;
+ }
+}
+protected void classInstanceCreation(boolean isQualified, boolean isShort) {
+ popElement(K_SELECTOR_QUALIFIER);
+ popElement(K_SELECTOR_INVOCATION_TYPE);
+ super.classInstanceCreation(isQualified, isShort);
+}
+public int getCursorLocation() {
+ return this.cursorLocation;
+}
+
+
+protected MessageSend newMessageSend() {
+ if (AssistParser.STOP_AT_CURSOR)
+ return super.newMessageSend();
+ // '(' ArgumentListopt ')'
+ // the arguments are on the expression stack
+
+ int numArgs=expressionLengthStack[expressionLengthPtr];
+ Expression receiver = expressionStack[expressionPtr-numArgs];
+
+// char[] selector = identifierStack[identifierPtr];
+// if (selector != this.assistIdentifier()){
+ if (!(receiver instanceof CompletionOnMemberAccess || receiver instanceof CompletionOnSingleNameReference))
+ {
+ return super.newMessageSend();
+ }
+ MessageSend messageSend = new CompletionOnMessageSend();
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ messageSend.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ assistNode = messageSend;
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+
+ this.isOrphanCompletionNode = true;
+ return messageSend;
+}
+
+protected JavadocParser createJavadocParser() {
+ return new CompletionJavadocParser(this);
+}
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser#createAssistTypeForAllocation(org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression)
+ */
+ public void createAssistTypeForAllocation(AllocationExpression expression) {
+ Expression member = expression.member;
+
+ /* create a CompletionOnSingleTypeReference from the existing
+ * member expression for the given allocation expression
+ */
+ if (member instanceof SingleNameReference) {
+ SingleNameReference snr = (SingleNameReference) member;
+ long position = (((long)snr.sourceStart)<<32)+snr.sourceEnd;
+ expression.member= new CompletionOnSingleTypeReference(snr.token,position);
+ ((CompletionOnSingleTypeReference)expression.member).isConstructorType = true;
+ }
+ else if(member instanceof CompletionOnMemberAccess) {
+ CompletionOnMemberAccess memberAccess = (CompletionOnMemberAccess) member;
+
+ //iterate over the receivers to build the token and find the start of the expression
+ IExpression receiver = memberAccess.getReceiver();
+ String token = new String(memberAccess.getToken());
+ int start = memberAccess.sourceStart();
+ while(receiver != null) {
+ start = receiver.sourceStart();
+ if(receiver instanceof IFieldReference) {
+ IFieldReference ref = (IFieldReference)receiver;
+ token = new String(ref.getToken()) + "." + token;
+ receiver = ref.getReceiver();
+ } else if(receiver instanceof ISingleNameReference) {
+ ISingleNameReference ref = (ISingleNameReference)receiver;
+ token = new String(ref.getToken()) + "." + token;
+ receiver = null;
+ }
+ }
+
+ //create and set the CompletionOnSingleTypeReference
+ long position = (((long)start)<<32)+memberAccess.sourceEnd;
+ expression.member = new CompletionOnSingleTypeReference(token.toCharArray(), position);
+ ((CompletionOnSingleTypeReference)expression.member).isConstructorType = true;
+ }
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionScanner.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionScanner.java
new file mode 100644
index 0000000..20033cf
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/CompletionScanner.java
@@ -0,0 +1,784 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/*
+ * Scanner aware of a cursor location so as to discard trailing portions of identifiers
+ * containing the cursor location.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ * -1 means completion at the very beginning of the source
+ * 0 means completion behind the first character
+ * n means completion behind the n-th character
+ */
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+
+public class CompletionScanner extends Scanner {
+
+
+ public char[] completionIdentifier;
+ public int cursorLocation;
+ public int endOfEmptyToken = -1;
+
+ /* Source positions of the completedIdentifier
+ * if inside actual identifier, end goes to the actual identifier
+ * end, in other words, beyond cursor location
+ */
+ public int completedIdentifierStart = 0;
+ public int completedIdentifierEnd = -1;
+ public int unicodeCharSize;
+
+
+ public static final char[] EmptyCompletionIdentifier = {};
+
+public CompletionScanner(long sourceLevel) {
+ super(
+ false /*comment*/,
+ false /*whitespace*/,
+ false /*nls*/,
+ sourceLevel,
+ null /*taskTags*/,
+ null/*taskPriorities*/,
+ true/*taskCaseSensitive*/);
+}
+
+/*
+ * Truncate the current identifier if it is containing the cursor location. Since completion is performed
+ * on an identifier prefix.
+ *
+ */
+public char[] getCurrentIdentifierSource() {
+
+ if (this.completionIdentifier == null){
+ if (this.cursorLocation < this.startPosition && this.currentPosition == this.startPosition){ // fake empty identifier got issued
+ // remember actual identifier positions
+ this.completedIdentifierStart = this.startPosition;
+ this.completedIdentifierEnd = this.completedIdentifierStart - 1;
+ return this.completionIdentifier = EmptyCompletionIdentifier;
+ }
+ if (this.cursorLocation+1 >= this.startPosition && this.cursorLocation < this.currentPosition){
+ // remember actual identifier positions
+ this.completedIdentifierStart = this.startPosition;
+ this.completedIdentifierEnd = this.currentPosition - 1;
+ if (this.withoutUnicodePtr != 0){ // check unicode scenario
+ int length = this.cursorLocation + 1 - this.startPosition - this.unicodeCharSize;
+ System.arraycopy(this.withoutUnicodeBuffer, 1, this.completionIdentifier = new char[length], 0, length);
+ } else {
+ // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
+ int length = this.cursorLocation + 1 - this.startPosition;
+ System.arraycopy(this.source, this.startPosition, (this.completionIdentifier = new char[length]), 0, length);
+ }
+ return this.completionIdentifier;
+ }
+ }
+ return super.getCurrentIdentifierSource();
+}
+
+public char[] getCurrentTokenSourceString() {
+ if (this.completionIdentifier == null){
+ if (this.cursorLocation+1 >= this.startPosition && this.cursorLocation < this.currentPosition){
+ // remember actual identifier positions
+ this.completedIdentifierStart = this.startPosition;
+ this.completedIdentifierEnd = this.currentPosition - 1;
+ if (this.withoutUnicodePtr != 0){ // check unicode scenario
+ int length = this.cursorLocation - this.startPosition - this.unicodeCharSize;
+ System.arraycopy(this.withoutUnicodeBuffer, 2, this.completionIdentifier = new char[length], 0, length);
+ } else {
+ // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
+ int length = this.cursorLocation - this.startPosition;
+ System.arraycopy(this.source, this.startPosition + 1, (this.completionIdentifier = new char[length]), 0, length);
+ }
+ return this.completionIdentifier;
+ }
+ }
+ return super.getCurrentTokenSourceString();
+}
+public int getNextToken() throws InvalidInputException {
+ if ( pushedBack ) {
+ pushedBack = false;
+ return currentToken;
+ }
+ int previousToken = this.currentToken;
+ this.wasAcr = false;
+ this.unicodeCharSize = 0;
+ if (this.diet) {
+ jumpOverMethodBody();
+ this.diet = false;
+ return (currentToken=this.currentPosition > this.eofPosition ? TokenNameEOF : TokenNameRBRACE);
+ }
+ int whiteStart = 0;
+ try {
+ while (true) { //loop for jumping over comments
+ this.withoutUnicodePtr = 0;
+ //start with a new token (even comment written with unicode )
+
+ // ---------Consume white space and handles start position---------
+ whiteStart = this.currentPosition;
+ boolean isWhiteSpace, hasWhiteSpaces = false;
+ int offset = 0;
+ do {
+ this.startPosition = this.currentPosition;
+ boolean checkIfUnicode = false;
+ try {
+ checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u');
+ } catch(IndexOutOfBoundsException e) {
+ if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+ // reposition scanner in case we are interested by spaces as tokens
+ this.currentPosition--;
+ this.startPosition = whiteStart;
+ return (currentToken=TokenNameWHITESPACE);
+ }
+ if (this.currentPosition > this.eofPosition) {
+ /* might be completing at eof (e.g. behind a dot) */
+ if (this.completionIdentifier == null &&
+ this.startPosition == this.cursorLocation + 1){
+ this.currentPosition = this.startPosition; // for being detected as empty free identifier
+ return TokenNameIdentifier;
+ }
+ return (currentToken=TokenNameEOF);
+ }
+ }
+ if (checkIfUnicode) {
+ isWhiteSpace = jumpOverUnicodeWhiteSpace();
+ offset = 6;
+ } else {
+ offset = 1;
+ if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+ //checkNonExternalizedString();
+ if (this.recordLineSeparator) {
+ pushLineSeparator();
+ }
+ }
+ isWhiteSpace =
+ (this.currentCharacter == ' ') || CharOperation.isWhitespace(this.currentCharacter);
+ }
+ if (isWhiteSpace) {
+ hasWhiteSpaces = true;
+ }
+ /* completion requesting strictly inside blanks */
+ if ((whiteStart != this.currentPosition)
+ //&& (previousToken == TokenNameDOT)
+ && (/* !AssistParser.STOP_AT_CURSOR || */ this.completionIdentifier == null)
+ && (whiteStart <= this.cursorLocation+1)
+ && (this.cursorLocation < this.startPosition)
+ && !ScannerHelper.isJavaIdentifierStart(this.currentCharacter)){
+// if (AssistParser.STOP_AT_CURSOR)
+ this.currentPosition = this.startPosition; // for next token read
+ return (currentToken=TokenNameIdentifier);
+ }
+ } while (isWhiteSpace);
+ if (this.tokenizeWhiteSpace && hasWhiteSpaces) {
+ // reposition scanner in case we are interested by spaces as tokens
+ this.currentPosition-=offset;
+ this.startPosition = whiteStart;
+ return (currentToken=TokenNameWHITESPACE);
+ }
+ //little trick to get out in the middle of a source computation
+ if (this.currentPosition > this.eofPosition ||(!AssistParser.STOP_AT_CURSOR && this.currentPosition > this.cursorLocation)){
+ /* might be completing at eof (e.g. behind a dot) */
+ if (this.completionIdentifier == null &&
+ this.startPosition == this.cursorLocation + 1){
+ // compute end of empty identifier.
+ // if the empty identifier is at the start of a next token the end of
+ // empty identifier is the end of the next token (eg. "next").
+ int temp = this.eofPosition;
+ this.eofPosition = this.source.length;
+ while(getNextCharAsJavaIdentifierPart()){/*empty*/}
+ this.eofPosition = temp;
+ this.endOfEmptyToken = this.currentPosition - 1;
+// this.currentPosition = this.startPosition; // for being detected as empty free identifier
+ return (currentToken=TokenNameIdentifier);
+ }
+ if (AssistParser.STOP_AT_CURSOR)
+ return (currentToken=TokenNameEOF);
+ }
+
+ // ---------Identify the next token-------------
+
+ switch (this.currentCharacter) {
+ case '(' :
+ return (currentToken=TokenNameLPAREN);
+ case ')' :
+ return (currentToken=TokenNameRPAREN);
+ case '{' :
+ return (currentToken=TokenNameLBRACE);
+ case '}' :
+ return (currentToken=TokenNameRBRACE);
+ case '[' :
+ return (currentToken=TokenNameLBRACKET);
+ case ']' :
+ return (currentToken=TokenNameRBRACKET);
+ case ';' :
+ return (currentToken=TokenNameSEMICOLON);
+ case ',' :
+ return (currentToken=TokenNameCOMMA);
+ case '.' :
+ if (this.startPosition <= this.cursorLocation
+ && this.cursorLocation < this.currentPosition){
+ return (currentToken=TokenNameDOT); // completion inside .<|>12
+ }
+ if (getNextCharAsDigit()) {
+ return (currentToken=scanNumber(true));
+ }
+ int temp = this.currentPosition;
+ if (getNextChar('.')) {
+// if (getNextChar('.')) {
+// return (currentToken=TokenNameELLIPSIS);
+// } else {
+ this.currentPosition = temp;
+ return (currentToken=TokenNameDOT);
+// }
+ } else {
+ this.currentPosition = temp;
+ return (currentToken=TokenNameDOT);
+ }
+ case '+' :
+ {
+ int test;
+ if ((test = getNextChar('+', '=')) == 0)
+ return (currentToken=TokenNamePLUS_PLUS);
+ if (test > 0)
+ return (currentToken=TokenNamePLUS_EQUAL);
+ return (currentToken=TokenNamePLUS);
+ }
+ case '-' :
+ {
+ int test;
+ if ((test = getNextChar('-', '=')) == 0)
+ return (currentToken=TokenNameMINUS_MINUS);
+ if (test > 0)
+ return (currentToken=TokenNameMINUS_EQUAL);
+ return (currentToken=TokenNameMINUS);
+ }
+ case '~' :
+ return (currentToken=TokenNameTWIDDLE);
+ case '!' :
+ if (getNextChar('='))
+ {
+ if (getNextChar('='))
+ {
+ currentToken=TokenNameNOT_EQUAL_EQUAL;
+ return currentToken;
+ }
+ currentToken=TokenNameNOT_EQUAL;
+ return currentToken;
+ }
+ currentToken=TokenNameNOT;
+ return currentToken;
+ case '*' :
+ if (getNextChar('='))
+ return (currentToken=TokenNameMULTIPLY_EQUAL);
+ return (currentToken=TokenNameMULTIPLY);
+ case '%' :
+ if (getNextChar('='))
+ return (currentToken=TokenNameREMAINDER_EQUAL);
+ return (currentToken=TokenNameREMAINDER);
+ case '<' :
+ {
+ int test;
+ if ((test = getNextChar('=', '<')) == 0)
+ return (currentToken=TokenNameLESS_EQUAL);
+ if (test > 0) {
+ if (getNextChar('='))
+ return (currentToken=TokenNameLEFT_SHIFT_EQUAL);
+ return (currentToken=TokenNameLEFT_SHIFT);
+ }
+ return (currentToken=TokenNameLESS);
+ }
+ case '>' :
+ {
+ int test;
+ if (this.returnOnlyGreater) {
+ return (currentToken=TokenNameGREATER);
+ }
+ if ((test = getNextChar('=', '>')) == 0)
+ return (currentToken=TokenNameGREATER_EQUAL);
+ if (test > 0) {
+ if ((test = getNextChar('=', '>')) == 0)
+ return (currentToken=TokenNameRIGHT_SHIFT_EQUAL);
+ if (test > 0) {
+ if (getNextChar('='))
+ return (currentToken=TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL);
+ return (currentToken=TokenNameUNSIGNED_RIGHT_SHIFT);
+ }
+ return (currentToken=TokenNameRIGHT_SHIFT);
+ }
+ return (currentToken=TokenNameGREATER);
+ }
+ case '=' :
+ if (getNextChar('='))
+ {
+ if (getNextChar('='))
+ {
+ currentToken=TokenNameEQUAL_EQUAL_EQUAL;
+ return currentToken;
+ }
+ currentToken=TokenNameEQUAL_EQUAL;
+ return currentToken;
+ }
+ currentToken=TokenNameEQUAL;
+ return currentToken;
+ case '&' :
+ {
+ int test;
+ if ((test = getNextChar('&', '=')) == 0)
+ return (currentToken=TokenNameAND_AND);
+ if (test > 0)
+ return (currentToken=TokenNameAND_EQUAL);
+ return (currentToken=TokenNameAND);
+ }
+ case '|' :
+ {
+ int test;
+ if ((test = getNextChar('|', '=')) == 0)
+ return (currentToken=TokenNameOR_OR);
+ if (test > 0)
+ return (currentToken=TokenNameOR_EQUAL);
+ return (currentToken=TokenNameOR);
+ }
+ case '^' :
+ if (getNextChar('='))
+ return (currentToken=TokenNameXOR_EQUAL);
+ return (currentToken=TokenNameXOR);
+ case '?' :
+ return (currentToken=TokenNameQUESTION);
+ case ':' :
+ return (currentToken=TokenNameCOLON);
+/* case '\'' :
+ {
+ int test;
+ if ((test = getNextChar('\n', '\r')) == 0) {
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+ }
+ if (test > 0) {
+ // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+ for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+ if (this.currentPosition + lookAhead == this.eofPosition)
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\n')
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\'') {
+ this.currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+ }
+ }
+ if (getNextChar('\'')) {
+ // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+ for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+ if (this.currentPosition + lookAhead == this.eofPosition)
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\n')
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\'') {
+ this.currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+ }
+ if (getNextChar('\\')) {
+ if (this.unicodeAsBackSlash) {
+ // consume next character
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStore();
+ }
+ }
+ } else {
+ this.currentCharacter = this.source[this.currentPosition++];
+ }
+ scanEscapeCharacter();
+ } else { // consume next character
+ this.unicodeAsBackSlash = false;
+ boolean checkIfUnicode = false;
+ try {
+ checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u');
+ } catch(IndexOutOfBoundsException e) {
+ this.currentPosition--;
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+ }
+ if (checkIfUnicode) {
+ getNextUnicodeChar();
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ this.unicodeStore();
+ }
+ }
+ }
+ if (getNextChar('\''))
+ return (currentToken=TokenNameCharacterLiteral);
+ // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+ for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
+ if (this.currentPosition + lookAhead == this.eofPosition)
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\n')
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\'') {
+ this.currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT); */
+ case '\'' :
+ case '"' :
+ char character = this.currentCharacter;
+ try {
+ // consume next character
+ this.unicodeAsBackSlash = false;
+ boolean isUnicode = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ isUnicode = true;
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ this.unicodeStore();
+ }
+ }
+
+ while ((this.currentCharacter != character) || ((this.currentCharacter == character) && (isUnicode == true))) {
+ if ((this.currentCharacter == '\n' && !isUnicode) || (this.currentCharacter == '\r' && !isUnicode)) {
+ this.currentPosition--; // set current position on new line character
+ if(this.startPosition <= this.cursorLocation
+ && this.cursorLocation <= this.currentPosition-1) {
+ // complete inside a string literal
+ return (currentToken=TokenNameStringLiteral);
+ }
+ throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+ }
+ if (this.currentCharacter == '\\') {
+ if (this.unicodeAsBackSlash) {
+ this.withoutUnicodePtr--;
+ // consume next character
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ isUnicode = true;
+ this.withoutUnicodePtr--;
+ } else {
+ isUnicode = false;
+ }
+ } else {
+ if (this.withoutUnicodePtr == 0) {
+ unicodeInitializeBuffer(this.currentPosition - this.startPosition);
+ }
+ this.withoutUnicodePtr --;
+ this.currentCharacter = this.source[this.currentPosition++];
+ }
+ // we need to compute the escape character in a separate buffer
+ if (scanEscapeCharacter() && this.withoutUnicodePtr != 0) {
+ unicodeStore();
+ }
+ }
+ // consume next character
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ isUnicode = true;
+ } else {
+ isUnicode = false;
+ if (this.withoutUnicodePtr != 0) {
+ this.unicodeStore();
+ }
+ }
+
+ }
+ } catch (IndexOutOfBoundsException e) {
+ this.currentPosition--;
+ if(this.startPosition <= this.cursorLocation
+ && this.cursorLocation < this.currentPosition) {
+ // complete inside a string literal
+ return (currentToken=TokenNameStringLiteral);
+ }
+ throw new InvalidInputException(UNTERMINATED_STRING);
+ } catch (InvalidInputException e) {
+ if (e.getMessage().equals(INVALID_ESCAPE)) {
+ // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+ for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+ if (this.currentPosition + lookAhead == this.eofPosition)
+ break;
+ if (this.source[this.currentPosition + lookAhead] == '\n')
+ break;
+ if (this.source[this.currentPosition + lookAhead] == character) {
+ this.currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+
+ }
+ throw e; // rethrow
+ }
+ if (character == '\'') {
+ return (currentToken=TokenNameCharacterLiteral);
+ } else {
+ return (currentToken=TokenNameStringLiteral);
+ }
+
+
+ case '/' :
+ {
+ int test;
+ if ((test = getNextChar('/', '*')) == 0) { //line comment
+ this.lastCommentLinePosition = this.currentPosition;
+ try { //get the next char
+ this.currentCharacter = this.source[this.currentPosition++];
+ while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
+ this.currentCharacter = this.source[this.currentPosition++];
+ }
+ /*
+ * We need to completely consume the line break
+ */
+ boolean isUnicode = false;
+ if (this.currentCharacter == '\r'
+ && this.eofPosition > this.currentPosition) {
+ if (this.source[this.currentPosition] == '\n') {
+ this.currentPosition++;
+ this.currentCharacter = '\n';
+ } else if ((this.source[this.currentPosition] == '\\')
+ && (this.source[this.currentPosition + 1] == 'u')) {
+ isUnicode = true;
+ char unicodeChar;
+ int index = this.currentPosition + 1;
+ index++;
+ while (this.source[index] == 'u') {
+ index++;
+ }
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ if ((c1 = ScannerHelper.getNumericValue(this.source[index++])) > 15
+ || c1 < 0
+ || (c2 = ScannerHelper.getNumericValue(this.source[index++])) > 15
+ || c2 < 0
+ || (c3 = ScannerHelper.getNumericValue(this.source[index++])) > 15
+ || c3 < 0
+ || (c4 = ScannerHelper.getNumericValue(this.source[index++])) > 15
+ || c4 < 0) {
+ this.currentPosition = index;
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ } else {
+ unicodeChar = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ if (unicodeChar == '\n') {
+ this.currentPosition = index;
+ this.currentCharacter = '\n';
+ }
+ }
+ }
+ recordComment(TokenNameCOMMENT_LINE);
+ if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
+ throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
+ }
+ if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+ if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+ //checkNonExternalizedString();
+ if (this.recordLineSeparator) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
+ pushLineSeparator();
+ }
+ }
+ }
+ if (this.tokenizeComments) {
+ return (currentToken=TokenNameCOMMENT_LINE);
+ }
+ } catch (IndexOutOfBoundsException e) {
+ this.currentPosition--;
+ recordComment(TokenNameCOMMENT_LINE);
+ if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+ if (this.tokenizeComments) {
+ return (currentToken=TokenNameCOMMENT_LINE);
+ } else {
+ this.currentPosition++;
+ }
+ }
+ break;
+ }
+ if (test > 0) { //traditional and javadoc comment
+ try { //get the next char
+ boolean isJavadoc = false, star = false;
+ boolean isUnicode = false;
+ // consume next character
+ this.currentCharacter = this.source[this.currentPosition++];
+
+ if (this.currentCharacter == '*') {
+ isJavadoc = true;
+ star = true;
+ }
+ if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+ //checkNonExternalizedString();
+ if (this.recordLineSeparator) {
+ if (!isUnicode) {
+ pushLineSeparator();
+ }
+ }
+ }
+ isUnicode = false;
+ this.currentCharacter = this.source[this.currentPosition++];
+ // empty comment is not a javadoc /**/
+ if (this.currentCharacter == '/') {
+ isJavadoc = false;
+ }
+ //loop until end of comment */
+ while ((this.currentCharacter != '/') || (!star)) {
+ if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+ //checkNonExternalizedString();
+ if (this.recordLineSeparator) {
+ if (!isUnicode) {
+ pushLineSeparator();
+ }
+ }
+ }
+ star = this.currentCharacter == '*';
+ //get next char
+ this.currentCharacter = this.source[this.currentPosition++];
+ }
+ int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK;
+ recordComment(token);
+ if (!isJavadoc && this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
+ throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
+ }
+ if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+ if (this.tokenizeComments) {
+ /*
+ if (isJavadoc)
+ return TokenNameCOMMENT_JAVADOC;
+ return TokenNameCOMMENT_BLOCK;
+ */
+ return (currentToken=token);
+ }
+ } catch (IndexOutOfBoundsException e) {
+ this.currentPosition--;
+ throw new InvalidInputException(UNTERMINATED_COMMENT);
+ }
+ break;
+ }
+ if (checkIfDivide(previousToken)){
+ if (getNextChar('='))
+ {
+ currentToken=TokenNameDIVIDE_EQUAL;
+ return currentToken;
+ }
+ currentToken=TokenNameDIVIDE;
+ return currentToken;
+ }
+
+ // check if regular expression
+ if (checkIfRegExp()) {
+ currentToken = TokenNameRegExLiteral;
+ return currentToken;
+ }
+ }
+ case '\u001a' :
+ if (atEnd())
+ return (currentToken=TokenNameEOF);
+ //the atEnd may not be if source is only some part of a real (external) stream
+ throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
+
+ default :
+ if (ScannerHelper.isJavaIdentifierStart(this.currentCharacter))
+ return (currentToken=scanIdentifierOrKeyword());
+ if (ScannerHelper.isDigit(this.currentCharacter)) {
+ return (currentToken=scanNumber(false));
+ }
+ return (currentToken=TokenNameERROR);
+ }
+ }
+ } //-----------------end switch while try--------------------
+ catch (IndexOutOfBoundsException e) {
+ if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+ // reposition scanner in case we are interested by spaces as tokens
+ this.currentPosition--;
+ this.startPosition = whiteStart;
+ return (currentToken=TokenNameWHITESPACE);
+ }
+ }
+ /* might be completing at very end of file (e.g. behind a dot) */
+ if (this.completionIdentifier == null &&
+ this.startPosition == this.cursorLocation + 1){
+ this.currentPosition = this.startPosition; // for being detected as empty free identifier
+ return (currentToken=TokenNameIdentifier);
+ }
+ return (currentToken=TokenNameEOF);
+}
+public final void getNextUnicodeChar() throws InvalidInputException {
+ int temp = this.currentPosition; // the \ is already read
+ super.getNextUnicodeChar();
+ if(this.cursorLocation > temp) {
+ this.unicodeCharSize += (this.currentPosition - temp);
+ }
+ if (temp < this.cursorLocation && this.cursorLocation < this.currentPosition-1){
+ throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_UNICODE);
+ }
+}
+public final void jumpOverBlock() {
+ this.jumpOverMethodBody();
+}
+
+
+///*
+// * In case we actually read a keyword, but the cursor is located inside,
+// * we pretend we read an identifier.
+// */
+public int scanIdentifierOrKeyword() {
+
+ int id = super.scanIdentifierOrKeyword();
+
+ if (this.startPosition <= this.cursorLocation+1
+ && this.cursorLocation < this.currentPosition){
+
+ // extends the end of the completion token even if the end is after eofPosition
+ if (this.cursorLocation+1 == this.eofPosition) {
+ int temp = this.eofPosition;
+ this.eofPosition = this.source.length;
+ while(getNextCharAsJavaIdentifierPart()){/*empty*/}
+ this.eofPosition = temp;
+ }
+ // convert completed keyword into an identifier
+ return TokenNameIdentifier;
+ }
+ return id;
+}
+
+
+public int scanNumber(boolean dotPrefix) throws InvalidInputException {
+
+ int token = super.scanNumber(dotPrefix);
+
+ // consider completion just before a number to be ok, will insert before it
+ if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition){
+ throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_NUMBER);
+ }
+ return token;
+}
+
+public void setSource(char[] sourceString) {
+ super.setSource(sourceString);
+ if (!Parser.DO_DIET_PARSE && AssistParser.STOP_AT_CURSOR)
+ this.eofPosition=this.cursorLocation+1;
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/InvalidCursorLocation.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/InvalidCursorLocation.java
new file mode 100644
index 0000000..cbc901d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/complete/InvalidCursorLocation.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.complete;
+
+/**
+ * Thrown whenever cursor location is not inside a consistent token
+ * for example: inside a string, number, unicode, comments etc...
+ */
+public class InvalidCursorLocation extends RuntimeException {
+
+ public String irritant;
+
+ /* Possible irritants */
+ public static final String NO_COMPLETION_INSIDE_UNICODE = "No Completion Inside Unicode"; //$NON-NLS-1$
+ public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment"; //$NON-NLS-1$
+ public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String"; //$NON-NLS-1$
+ public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number"; //$NON-NLS-1$
+
+ private static final long serialVersionUID = -3443160725735779590L; // backward compatible
+
+public InvalidCursorLocation(String irritant){
+ this.irritant = irritant;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/AssistOptions.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/AssistOptions.java
new file mode 100644
index 0000000..4009b59
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/AssistOptions.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.impl;
+
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+
+public class AssistOptions {
+ /**
+ * Option IDs
+ */
+ public static final String OPTION_PerformVisibilityCheck =
+ "org.eclipse.wst.jsdt.core.codeComplete.visibilityCheck"; //$NON-NLS-1$
+ public static final String OPTION_PerformDeprecationCheck =
+ "org.eclipse.wst.jsdt.core.codeComplete.deprecationCheck"; //$NON-NLS-1$
+ public static final String OPTION_ForceImplicitQualification =
+ "org.eclipse.wst.jsdt.core.codeComplete.forceImplicitQualification"; //$NON-NLS-1$
+ public static final String OPTION_FieldPrefixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.fieldPrefixes"; //$NON-NLS-1$
+ public static final String OPTION_StaticFieldPrefixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.staticFieldPrefixes"; //$NON-NLS-1$
+ public static final String OPTION_LocalPrefixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.localPrefixes"; //$NON-NLS-1$
+ public static final String OPTION_ArgumentPrefixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.argumentPrefixes"; //$NON-NLS-1$
+ public static final String OPTION_FieldSuffixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.fieldSuffixes"; //$NON-NLS-1$
+ public static final String OPTION_StaticFieldSuffixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.staticFieldSuffixes"; //$NON-NLS-1$
+ public static final String OPTION_LocalSuffixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.localSuffixes"; //$NON-NLS-1$
+ public static final String OPTION_ArgumentSuffixes =
+ "org.eclipse.wst.jsdt.core.codeComplete.argumentSuffixes"; //$NON-NLS-1$
+ public static final String OPTION_PerformForbiddenReferenceCheck =
+ "org.eclipse.wst.jsdt.core.codeComplete.forbiddenReferenceCheck"; //$NON-NLS-1$
+ public static final String OPTION_PerformDiscouragedReferenceCheck =
+ "org.eclipse.wst.jsdt.core.codeComplete.discouragedReferenceCheck"; //$NON-NLS-1$
+ public static final String OPTION_CamelCaseMatch =
+ "org.eclipse.wst.jsdt.core.codeComplete.camelCaseMatch"; //$NON-NLS-1$
+ public static final String OPTION_SuggestStaticImports =
+ "org.eclipse.wst.jsdt.core.codeComplete.suggestStaticImports"; //$NON-NLS-1$
+
+ public static final String ENABLED = "enabled"; //$NON-NLS-1$
+ public static final String DISABLED = "disabled"; //$NON-NLS-1$
+
+ public boolean checkVisibility = false;
+ public boolean checkDeprecation = false;
+ public boolean checkForbiddenReference = false;
+ public boolean checkDiscouragedReference = false;
+ public boolean forceImplicitQualification = false;
+ public boolean camelCaseMatch = true;
+ public boolean suggestStaticImport = true;
+ public char[][] fieldPrefixes = null;
+ public char[][] staticFieldPrefixes = null;
+ public char[][] localPrefixes = null;
+ public char[][] argumentPrefixes = null;
+ public char[][] fieldSuffixes = null;
+ public char[][] staticFieldSuffixes = null;
+ public char[][] localSuffixes = null;
+ public char[][] argumentSuffixes = null;
+
+ /**
+ * Initializing the assist options with default settings
+ */
+ public AssistOptions() {
+ // Initializing the assist options with default settings
+ }
+
+ /**
+ * Initializing the assist options with external settings
+ */
+ public AssistOptions(Map settings) {
+ if (settings == null)
+ return;
+
+ set(settings);
+ }
+ public void set(Map optionsMap) {
+
+ Object optionValue;
+ if ((optionValue = optionsMap.get(OPTION_PerformVisibilityCheck)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.checkVisibility = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.checkVisibility = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ForceImplicitQualification)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.forceImplicitQualification = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.forceImplicitQualification = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_FieldPrefixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.fieldPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.fieldPrefixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_StaticFieldPrefixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.staticFieldPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.staticFieldPrefixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_LocalPrefixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.localPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.localPrefixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ArgumentPrefixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.argumentPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.argumentPrefixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_FieldSuffixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.fieldSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.fieldSuffixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_StaticFieldSuffixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.staticFieldSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.staticFieldSuffixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_LocalSuffixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.localSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.localSuffixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ArgumentSuffixes)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() > 0){
+ this.argumentSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
+ } else {
+ this.argumentSuffixes = null;
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_PerformForbiddenReferenceCheck)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.checkForbiddenReference = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.checkForbiddenReference = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_PerformDiscouragedReferenceCheck)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.checkDiscouragedReference = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.checkDiscouragedReference = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_CamelCaseMatch)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.camelCaseMatch = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.camelCaseMatch = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_PerformDeprecationCheck)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.checkDeprecation = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.checkDeprecation = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_SuggestStaticImports)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.suggestStaticImport = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.suggestStaticImport = false;
+ }
+ }
+ }
+
+ private char[][] splitAndTrimOn(char divider, char[] arrayToSplit) {
+ char[][] result = CharOperation.splitAndTrimOn(',', arrayToSplit);
+
+ int length = result.length;
+
+ int resultCount = 0;
+ for (int i = 0; i < length; i++) {
+ if(result[i].length != 0) {
+ result[resultCount++] = result[i];
+ }
+ }
+ if(resultCount != length) {
+ System.arraycopy(result, 0, result = new char[resultCount][], 0, resultCount);
+ }
+ return result;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/AssistParser.java
new file mode 100644
index 0000000..76daa13
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/AssistParser.java
@@ -0,0 +1,1314 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.impl;
+
+/*
+ * Parser extension for code assist task
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Statement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredBlock;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredElement;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredField;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredMethod;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredType;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+
+public abstract class AssistParser extends Parser {
+
+ // Default behavior is to stop parsing at the cursor position, but
+ // we need to parse fully so that types can be inferred
+ public static final boolean STOP_AT_CURSOR=false;
+
+ public ASTNode assistNode;
+ public boolean isOrphanCompletionNode;
+
+ /* recovery */
+ int[] blockStarts = new int[30];
+
+ // the previous token read by the scanner
+ protected int previousToken;
+
+ // the index in the identifier stack of the previous identifier
+ protected int previousIdentifierPtr;
+
+ // element stack
+ protected static final int ElementStackIncrement = 100;
+ protected int elementPtr;
+ protected int[] elementKindStack = new int[ElementStackIncrement];
+ protected int[] elementInfoStack = new int[ElementStackIncrement];
+ protected int previousKind;
+ protected int previousInfo;
+
+ // OWNER
+ protected static final int ASSIST_PARSER = 512;
+
+ // KIND : all values known by AssistParser are between 513 and 1023
+ protected static final int K_SELECTOR = ASSIST_PARSER + 1; // whether we are inside a message send
+ protected static final int K_TYPE_DELIMITER = ASSIST_PARSER + 2; // whether we are inside a type declaration
+ protected static final int K_METHOD_DELIMITER = ASSIST_PARSER + 3; // whether we are inside a method declaration
+ protected static final int K_FIELD_INITIALIZER_DELIMITER = ASSIST_PARSER + 4; // whether we are inside a field initializer
+ protected static final int K_ATTRIBUTE_VALUE_DELIMITER = ASSIST_PARSER + 5; // whether we are inside a annotation attribute valuer
+ protected static final int K_ENUM_CONSTANT_DELIMITER = ASSIST_PARSER + 6; // whether we are inside a field initializer
+
+ // selector constants
+ protected static final int THIS_CONSTRUCTOR = -1;
+ protected static final int SUPER_CONSTRUCTOR = -2;
+
+ // enum constant constants
+ protected static final int NO_BODY = 0;
+ protected static final int WITH_BODY = 1;
+
+ protected boolean isFirst = false;
+
+public AssistParser(ProblemReporter problemReporter) {
+ super(problemReporter, true);
+ this.javadocParser.checkDocComment = false;
+
+ this.setMethodsFullRecovery(false);
+ this.setStatementsRecovery(false);
+}
+public abstract char[] assistIdentifier();
+public int bodyEnd(AbstractMethodDeclaration method){
+ return method.bodyEnd;
+}
+public int bodyEnd(Initializer initializer){
+ return initializer.declarationSourceEnd;
+}
+/*
+ * Build initial recovery state.
+ * Recovery state is inferred from the current state of the parser (reduced node stack).
+ */
+public RecoveredElement buildInitialRecoveryState(){
+ /* recovery in unit structure */
+ if (referenceContext instanceof CompilationUnitDeclaration){
+ boolean oldStatementRecoveryActivated = this.statementRecoveryActivated;
+ if (!DO_DIET_PARSE)
+ this.statementRecoveryActivated=true;
+ RecoveredElement element = super.buildInitialRecoveryState();
+ this.statementRecoveryActivated=oldStatementRecoveryActivated;
+ flushAssistState();
+ flushElementStack();
+ if (element instanceof RecoveredMethod)
+ pushOnElementStack(K_METHOD_DELIMITER);
+ return element;
+ }
+
+ /* recovery in method body */
+ lastCheckPoint = 0;
+
+ RecoveredElement element = null;
+ if (referenceContext instanceof AbstractMethodDeclaration){
+ element = new RecoveredMethod((AbstractMethodDeclaration) referenceContext, null, 0, this);
+ lastCheckPoint = ((AbstractMethodDeclaration) referenceContext).bodyStart;
+ } else {
+ /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
+ if (referenceContext instanceof TypeDeclaration){
+ TypeDeclaration type = (TypeDeclaration) referenceContext;
+ for (int i = 0; i < type.fields.length; i++){
+ FieldDeclaration field = type.fields[i];
+ if (field != null
+ && field.getKind() == AbstractVariableDeclaration.INITIALIZER
+ && field.declarationSourceStart <= scanner.initialPosition
+ && scanner.initialPosition <= field.declarationSourceEnd
+ && scanner.eofPosition <= field.declarationSourceEnd+1){
+ element = new RecoveredInitializer(field, null, 1, this);
+ lastCheckPoint = field.declarationSourceStart;
+ break;
+ }
+ }
+ }
+ }
+
+ if (element == null) return element;
+
+ /* add initial block */
+ Block block = new Block(0);
+ int lastStart = blockStarts[0];
+ block.sourceStart = lastStart;
+ element = element.add(block, 1);
+ int blockIndex = 1; // ignore first block start, since manually rebuilt here
+
+ for(int i = 0; i <= astPtr; i++){
+ ASTNode node = astStack[i];
+
+ if(node instanceof ForeachStatement && ((ForeachStatement)node).action == null) {
+ node = ((ForeachStatement)node).elementVariable;
+ }
+
+ /* check for intermediate block creation, so recovery can properly close them afterwards */
+ int nodeStart = node.sourceStart;
+ for (int j = blockIndex; j <= realBlockPtr; j++) {
+ if (blockStarts[j] >= 0) {
+ if (blockStarts[j] > nodeStart) {
+ blockIndex = j; // shift the index to the new block
+ break;
+ }
+ if (blockStarts[j] != lastStart) { // avoid multiple block
+ // if at same position
+ block = new Block(0);
+ block.sourceStart = lastStart = blockStarts[j];
+ element = element.add(block, 1);
+ }
+ blockIndex = j + 1; // shift the index to the new block
+ } else {
+ if (-blockStarts[j] > nodeStart) {
+ blockIndex = j; // shift the index to the new block
+ break;
+ }
+ block = new Block(0);
+ block.sourceStart = lastStart = -blockStarts[j];
+ element = element.add(block, 1);
+ }
+ }
+ if (node instanceof LocalDeclaration){
+ LocalDeclaration local = (LocalDeclaration) node;
+ if (local.declarationSourceEnd == 0){
+ element = element.add(local, 0);
+ if (local.initialization == null){
+ lastCheckPoint = local.sourceEnd + 1;
+ } else {
+ lastCheckPoint = local.initialization.sourceEnd + 1;
+ }
+ } else {
+ element = element.add(local, 0);
+ lastCheckPoint = local.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof AbstractMethodDeclaration){
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
+ if (method.declarationSourceEnd == 0){
+ element = element.add(method, 0);
+ lastCheckPoint = method.bodyStart;
+ } else {
+ element = element.add(method, 0);
+ lastCheckPoint = method.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof Initializer){
+ Initializer initializer = (Initializer) node;
+ if (initializer.declarationSourceEnd == 0){
+ element = element.add(initializer, 1);
+ lastCheckPoint = initializer.sourceStart;
+ } else {
+ element = element.add(initializer, 0);
+ lastCheckPoint = initializer.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof FieldDeclaration){
+ FieldDeclaration field = (FieldDeclaration) node;
+ if (field.declarationSourceEnd == 0){
+ element = element.add(field, 0);
+ if (field.initialization == null){
+ lastCheckPoint = field.sourceEnd + 1;
+ } else {
+ lastCheckPoint = field.initialization.sourceEnd + 1;
+ }
+ } else {
+ element = element.add(field, 0);
+ lastCheckPoint = field.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof TypeDeclaration){
+ TypeDeclaration type = (TypeDeclaration) node;
+ if (type.declarationSourceEnd == 0){
+ element = element.add(type, 0);
+ lastCheckPoint = type.bodyStart;
+ } else {
+ element = element.add(type, 0);
+ lastCheckPoint = type.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof ImportReference){
+ ImportReference importRef = (ImportReference) node;
+ element = element.add(importRef, 0);
+ lastCheckPoint = importRef.declarationSourceEnd + 1;
+ }
+ }
+ if (this.currentToken == TokenNameRBRACE) {
+ this.currentToken = 0; // closing brace has already been taken care of
+ }
+
+ /* might need some extra block (after the last reduced node) */
+ int pos = this.assistNode == null ? lastCheckPoint : this.assistNode.sourceStart;
+ for (int j = blockIndex; j <= realBlockPtr; j++){
+ if (blockStarts[j] >= 0) {
+ if ((blockStarts[j] < pos) && (blockStarts[j] != lastStart)){ // avoid multiple block if at same position
+ block = new Block(0);
+ block.sourceStart = lastStart = blockStarts[j];
+ element = element.add(block, 1);
+ }
+ } else {
+ if ((blockStarts[j] < pos)){ // avoid multiple block if at same position
+ block = new Block(0);
+ block.sourceStart = lastStart = -blockStarts[j];
+ element = element.add(block, 1);
+ }
+ }
+ }
+
+ return element;
+}
+protected void consumeForceNoDiet() {
+ super.consumeForceNoDiet();
+ // if we are not in a method (ie. we are not in a local variable initializer)
+ // then we are entering a field initializer
+ if (!isInsideMethod()) {
+ if(topKnownElementKind(ASSIST_PARSER) != K_ENUM_CONSTANT_DELIMITER) {
+ if(topKnownElementKind(ASSIST_PARSER, 2) != K_ENUM_CONSTANT_DELIMITER) {
+ pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
+ }
+ } else {
+ int info = topKnownElementInfo(ASSIST_PARSER);
+ if(info != NO_BODY) {
+ pushOnElementStack(K_FIELD_INITIALIZER_DELIMITER);
+ }
+ }
+
+ }
+}
+protected void consumeMethodBody() {
+ super.consumeMethodBody();
+ popElement(K_METHOD_DELIMITER);
+}
+protected void consumeMethodHeader() {
+ super.consumeMethodHeader();
+ pushOnElementStack(K_METHOD_DELIMITER);
+}
+protected void consumeCallExpressionWithArguments() {
+ super.consumeCallExpressionWithArguments();
+ popElement(K_SELECTOR);
+ MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+ if (messageSend == assistNode){
+ this.lastCheckPoint = messageSend.sourceEnd + 1;
+ }
+}
+protected void consumeNestedMethod() {
+ super.consumeNestedMethod();
+ if(!isInsideMethod()) pushOnElementStack(K_METHOD_DELIMITER);
+}
+protected void consumeOpenBlock() {
+ // OpenBlock ::= $empty
+
+ super.consumeOpenBlock();
+ int stackLength = this.blockStarts.length;
+ if (this.realBlockPtr >= stackLength) {
+ System.arraycopy(
+ this.blockStarts, 0,
+ this.blockStarts = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.blockStarts[this.realBlockPtr] = scanner.startPosition;
+}
+protected void consumeOpenFakeBlock() {
+ // OpenBlock ::= $empty
+
+ super.consumeOpenBlock();
+ int stackLength = this.blockStarts.length;
+ if (this.realBlockPtr >= stackLength) {
+ System.arraycopy(
+ this.blockStarts, 0,
+ this.blockStarts = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.blockStarts[this.realBlockPtr] = -scanner.startPosition;
+}
+
+protected void consumeRestoreDiet() {
+ super.consumeRestoreDiet();
+ // if we are not in a method (ie. we were not in a local variable initializer)
+ // then we are exiting a field initializer
+ if (!isInsideMethod()) {
+ popElement(K_FIELD_INITIALIZER_DELIMITER);
+ }
+}
+
+protected void consumeToken(int token) {
+ super.consumeToken(token);
+
+ if(isFirst) {
+ isFirst = false;
+ return;
+ }
+ // register message send selector only if inside a method or if looking at a field initializer
+ // and if the current token is an open parenthesis
+ if (isInsideMethod() || isInsideFieldInitialization() || isInsideAttributeValue()) {
+ switch (token) {
+ case TokenNameLPAREN :
+ switch (this.previousToken) {
+ case TokenNameIdentifier:
+ this.pushOnElementStack(K_SELECTOR, this.previousIdentifierPtr);
+ break;
+ case TokenNamethis: // explicit constructor invocation, eg. this(1, 2)
+ this.pushOnElementStack(K_SELECTOR, THIS_CONSTRUCTOR);
+ break;
+ case TokenNamesuper: // explicit constructor invocation, eg. super(1, 2)
+ this.pushOnElementStack(K_SELECTOR, SUPER_CONSTRUCTOR);
+ break;
+ case TokenNameGREATER: // explicit constructor invocation, eg. Fred[(]1, 2)
+ case TokenNameRIGHT_SHIFT: // or fred>[(]1, 2)
+ case TokenNameUNSIGNED_RIGHT_SHIFT: //or Fred>>[(]1, 2)
+ if(this.identifierPtr > -1) {
+ this.pushOnElementStack(K_SELECTOR, this.previousIdentifierPtr);
+ }
+ break;
+ }
+ break;
+ }
+ } else {
+ switch (token) {
+ case TokenNameRBRACE :
+ if(topKnownElementKind(ASSIST_PARSER) == K_TYPE_DELIMITER) {
+ popElement(K_TYPE_DELIMITER);
+ }
+ break;
+ }
+ }
+ this.previousToken = token;
+ if (token == TokenNameIdentifier) {
+ this.previousIdentifierPtr = this.identifierPtr;
+ }
+}
+public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions);
+public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
+public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
+public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
+public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
+public abstract void createAssistTypeForAllocation(AllocationExpression expression);
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+
+public abstract int getCursorLocation();
+
+public void flushAssistState(){
+ if (STOP_AT_CURSOR || this.lastCheckPoint 0 && this.genericsIdentifiersLengthPtr > -1 ) {
+ length = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr];
+ }
+ for (int i = 0; i < length; i++){
+ if (identifierStack[identifierPtr - i] == assistIdentifier){
+ return length - i - 1;
+ }
+ }
+ // none of the awaiting identifiers is the completion one
+ return -1;
+}
+public void initialize() {
+ super.initialize();
+ this.flushAssistState();
+ this.flushElementStack();
+ this.previousIdentifierPtr = -1;
+}
+public void initialize(boolean initializeNLS) {
+ super.initialize(initializeNLS);
+ this.flushAssistState();
+ this.flushElementStack();
+ this.previousIdentifierPtr = -1;
+}
+public abstract void initializeScanner();
+protected boolean isIndirectlyInsideFieldInitialization(){
+ int i = elementPtr;
+ while(i > -1) {
+ if(elementKindStack[i] == K_FIELD_INITIALIZER_DELIMITER)
+ return true;
+ i--;
+ }
+ return false;
+}
+protected boolean isIndirectlyInsideMethod(){
+ int i = elementPtr;
+ while(i > -1) {
+ if(elementKindStack[i] == K_METHOD_DELIMITER)
+ return true;
+ i--;
+ }
+ return false;
+}
+protected boolean isIndirectlyInsideType(){
+ int i = elementPtr;
+ while(i > -1) {
+ if(elementKindStack[i] == K_TYPE_DELIMITER)
+ return true;
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideAttributeValue(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ case K_ATTRIBUTE_VALUE_DELIMITER : return true;
+ }
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideFieldInitialization(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return true;
+ }
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideMethod(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return false;
+ case K_METHOD_DELIMITER : return true;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ }
+ i--;
+ }
+ return false;
+}
+protected boolean isInsideType(){
+ int i = elementPtr;
+ while(i > -1) {
+ switch (elementKindStack[i]) {
+ case K_TYPE_DELIMITER : return true;
+ case K_METHOD_DELIMITER : return false;
+ case K_FIELD_INITIALIZER_DELIMITER : return false;
+ }
+ i--;
+ }
+ return false;
+}
+protected int lastIndexOfElement(int kind) {
+ int i = elementPtr;
+ while(i > -1) {
+ if(elementKindStack[i] == kind) return i;
+ i--;
+ }
+ return -1;
+}
+/**
+ * Parse the block statements inside the given method declaration and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(AbstractMethodDeclaration md, CompilationUnitDeclaration unit) {
+ if (md instanceof MethodDeclaration) {
+ parseBlockStatements((MethodDeclaration) md, unit);
+ } else if (md instanceof ConstructorDeclaration) {
+ parseBlockStatements((ConstructorDeclaration) md, unit);
+ }
+}
+/**
+ * Parse the block statements inside the given constructor declaration and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
+ //only parse the method body of cd
+ //fill out its statements
+
+ //convert bugs into parse error
+
+ initialize();
+
+ // simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced
+ goForBlockStatementsopt();
+
+ referenceContext = cd;
+ compilationUnit = unit;
+
+ scanner.resetTo(cd.bodyStart, bodyEnd(cd));
+ consumeNestedMethod();
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ }
+
+ if (lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ // attach the statements as we might be searching for a reference to a local type
+ cd.explicitDeclarations = realBlockStack[realBlockPtr--];
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
+ //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+ {
+ System.arraycopy(
+ astStack,
+ astPtr + 2,
+ cd.statements = new Statement[length - 1],
+ 0,
+ length - 1);
+ cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
+ } else { //need to add explicitly the super();
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ cd.statements = new Statement[length],
+ 0,
+ length);
+ cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+ }
+ } else {
+ cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+ if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
+ cd.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ }
+
+ if (cd.constructorCall.sourceEnd == 0) {
+ cd.constructorCall.sourceEnd = cd.sourceEnd;
+ cd.constructorCall.sourceStart = cd.sourceStart;
+ }
+}
+/**
+ * Parse the block statements inside the given initializer and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(
+ Initializer initializer,
+ TypeDeclaration type,
+ CompilationUnitDeclaration unit) {
+
+ initialize();
+
+ // simulate goForInitializer except that we don't want to balance brackets because they are not going to be balanced
+ goForBlockStatementsopt();
+
+ referenceContext = type;
+ compilationUnit = unit;
+
+ scanner.resetTo(initializer.sourceStart, bodyEnd(initializer)); // just after the beginning {
+ consumeNestedMethod();
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ } finally {
+ nestedMethod[nestedType]--;
+ }
+
+ if (lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ // attach the statements as we might be searching for a reference to a local type
+ initializer.block.explicitDeclarations = realBlockStack[realBlockPtr--];
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) > 0) {
+ System.arraycopy(astStack, (astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length);
+ } else {
+ // check whether this block at least contains some comment in it
+ if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
+ initializer.block.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ }
+
+ // mark initializer with local type if one was found during parsing
+ if ((type.bits & ASTNode.HasLocalType) != 0) {
+ initializer.bits |= ASTNode.HasLocalType;
+ }
+}
+/**
+ * Parse the block statements inside the given method declaration and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(MethodDeclaration md, CompilationUnitDeclaration unit) {
+ //only parse the method body of md
+ //fill out method statements
+
+ //convert bugs into parse error
+
+ if (md.isAbstract())
+ return;
+ if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
+ return;
+
+ initialize();
+
+ // simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
+ goForBlockStatementsopt();
+
+ referenceContext = md;
+ compilationUnit = unit;
+
+ scanner.resetTo(md.bodyStart, bodyEnd(md)); // reset the scanner to parser from { down to the cursor location
+ consumeNestedMethod();
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ } finally {
+ nestedMethod[nestedType]--;
+ }
+
+ if (lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ // attach the statements as we might be searching for a reference to a local type
+ md.explicitDeclarations = realBlockStack[realBlockPtr--];
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ System.arraycopy(
+ astStack,
+ (astPtr -= length) + 1,
+ md.statements = new Statement[length],
+ 0,
+ length);
+ } else {
+ if (!containsComment(md.bodyStart, md.bodyEnd)) {
+ md.bits |= ASTNode.UndocumentedEmptyBlock;
+ }
+ }
+
+}
+protected void popElement(int kind){
+ if(elementPtr < 0 || elementKindStack[elementPtr] != kind) return;
+
+ previousKind = elementKindStack[elementPtr];
+ previousInfo = elementInfoStack[elementPtr];
+
+ switch (kind) {
+ default :
+ elementPtr--;
+ break;
+ }
+}
+protected void popUntilElement(int kind){
+ if(elementPtr < 0) return;
+ int i = elementPtr;
+ while (i >= 0 && elementKindStack[i] != kind) {
+ i--;
+ }
+ if(i >= 0) {
+ if(i < elementPtr) {
+ previousKind = elementKindStack[i+1];
+ previousInfo = elementInfoStack[i+1];
+ }
+ elementPtr = i;
+ }
+}
+/*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+protected void prepareForBlockStatements() {
+ this.nestedMethod[this.nestedType = 0] = 1;
+ this.variablesCounter[this.nestedType] = 0;
+ this.realBlockStack[this.realBlockPtr = 1] = 0;
+
+ // initialize element stack
+ int fieldInitializerIndex = lastIndexOfElement(K_FIELD_INITIALIZER_DELIMITER);
+ int methodIndex = lastIndexOfElement(K_METHOD_DELIMITER);
+ if(methodIndex == fieldInitializerIndex) {
+ // there is no method and no field initializer
+ flushElementStack();
+ } else if(methodIndex > fieldInitializerIndex) {
+ popUntilElement(K_METHOD_DELIMITER);
+ } else {
+ popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
+ }
+}
+/*
+ * Prepares the state of the parser to go for Headers.
+ */
+protected void prepareForHeaders() {
+ nestedMethod[nestedType = 0] = 0;
+ variablesCounter[nestedType] = 0;
+ realBlockStack[realBlockPtr = 0] = 0;
+
+// popUntilElement(K_TYPE_DELIMITER);
+//
+// if(this.topKnownElementKind(ASSIST_PARSER) != K_TYPE_DELIMITER) {
+// // is outside a type and inside a compilation unit.
+// // remove all elements.
+// this.flushElementStack();
+// }
+}
+protected void pushOnElementStack(int kind){
+ this.pushOnElementStack(kind, 0);
+}
+protected void pushOnElementStack(int kind, int info){
+ if (this.elementPtr < -1) return;
+
+ this.previousKind = 0;
+ this.previousInfo = 0;
+
+ int stackLength = this.elementKindStack.length;
+ if (++this.elementPtr >= stackLength) {
+ System.arraycopy(
+ this.elementKindStack, 0,
+ this.elementKindStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ System.arraycopy(
+ this.elementInfoStack, 0,
+ this.elementInfoStack = new int[stackLength + StackIncrement], 0,
+ stackLength);
+ }
+ this.elementKindStack[this.elementPtr] = kind;
+ this.elementInfoStack[this.elementPtr] = info;
+}
+public void recoveryExitFromVariable() {
+ if(currentElement != null && currentElement instanceof RecoveredField
+ && !(currentElement instanceof RecoveredInitializer)) {
+ RecoveredElement oldElement = currentElement;
+ super.recoveryExitFromVariable();
+ if(oldElement != currentElement) {
+ popElement(K_FIELD_INITIALIZER_DELIMITER);
+ }
+ } else {
+ super.recoveryExitFromVariable();
+ }
+}
+public void recoveryTokenCheck() {
+ RecoveredElement oldElement = currentElement;
+ switch (currentToken) {
+ case TokenNameLBRACE :
+ super.recoveryTokenCheck();
+ if(currentElement instanceof RecoveredInitializer) {
+ if(oldElement instanceof RecoveredField) {
+ popUntilElement(K_FIELD_INITIALIZER_DELIMITER);
+ popElement(K_FIELD_INITIALIZER_DELIMITER);
+ }
+ if(currentElement != oldElement
+ && topKnownElementKind(ASSIST_PARSER) != K_METHOD_DELIMITER) {
+ pushOnElementStack(K_METHOD_DELIMITER);
+ }
+ }
+ break;
+ case TokenNameRBRACE :
+ super.recoveryTokenCheck();
+ if(currentElement != oldElement && !isInsideAttributeValue()) {
+ if(oldElement instanceof RecoveredInitializer
+ || oldElement instanceof RecoveredMethod
+ || (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredInitializer)
+ || (oldElement instanceof RecoveredBlock && oldElement.parent instanceof RecoveredMethod)) {
+ popUntilElement(K_METHOD_DELIMITER);
+ popElement(K_METHOD_DELIMITER);
+ } else if(oldElement instanceof RecoveredType) {
+ popUntilElement(K_TYPE_DELIMITER);
+ if(!(referenceContext instanceof CompilationUnitDeclaration)
+ || isIndirectlyInsideFieldInitialization()
+ || currentElement instanceof RecoveredUnit) {
+ popElement(K_TYPE_DELIMITER);
+ }
+ }
+ }
+ break;
+ default :
+ super.recoveryTokenCheck();
+ break;
+ }
+}
+public void reset(){
+ this.flushAssistState();
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+ // reset internal stacks
+ this.astPtr = -1;
+ this.astLengthPtr = -1;
+ this.expressionPtr = -1;
+ this.expressionLengthPtr = -1;
+ this.identifierPtr = -1;
+ this.identifierLengthPtr = -1;
+ this.intPtr = -1;
+ this.dimensions = 0 ;
+ this.recoveredStaticInitializerStart = 0;
+
+ this.genericsIdentifiersLengthPtr = -1;
+ this.genericsLengthPtr = -1;
+ this.genericsPtr = -1;
+
+ this.modifiers = ClassFileConstants.AccDefault;
+ this.modifiersSourceStart = -1;
+
+ // if in diet mode, reset the diet counter because we're going to restart outside an initializer.
+ if (diet) dietInt = 0;
+
+ /* attempt to move checkpoint location */
+ if (!this.moveRecoveryCheckpoint()) return false;
+
+ // only look for headers
+ if (referenceContext instanceof CompilationUnitDeclaration
+ || this.assistNode != null){
+ if(isInsideMethod() &&
+ isIndirectlyInsideFieldInitialization() &&
+ this.assistNode == null
+ ){
+ this.prepareForBlockStatements();
+ goForBlockStatementsOrCatchHeader();
+ } else {
+ this.prepareForHeaders();
+ if (DO_DIET_PARSE)
+ {
+ goForHeaders();
+ this.diet = true; // passed this point, will not consider method bodies
+ }
+ else
+ goForProgramElements();
+ }
+ return true;
+ }
+ if (referenceContext instanceof AbstractMethodDeclaration
+ || referenceContext instanceof TypeDeclaration){
+
+ if (currentElement instanceof RecoveredType){
+ this.prepareForHeaders();
+ goForHeaders();
+ } else {
+ this.prepareForBlockStatements();
+ goForBlockStatementsOrCatchHeader();
+ }
+ return true;
+ }
+ // does not know how to restart
+ return false;
+}
+public abstract void setAssistIdentifier(char[] assistIdent);
+protected int topKnownElementInfo(int owner) {
+ return topKnownElementInfo(owner, 0);
+}
+protected int topKnownElementInfo(int owner, int offSet) {
+ int i = elementPtr;
+ while(i > -1) {
+ if((elementKindStack[i] & owner) != 0) {
+ if(offSet <= 0) return elementInfoStack[i];
+ offSet--;
+ }
+ i--;
+ }
+ return 0;
+}
+protected int topKnownElementKind(int owner) {
+ return topKnownElementKind(owner, 0);
+}
+protected int topKnownElementKind(int owner, int offSet) {
+ int i = elementPtr;
+ while(i > -1) {
+ if((elementKindStack[i] & owner) != 0) {
+ if(offSet <= 0) return elementKindStack[i];
+ offSet--;
+ }
+ i--;
+ }
+ return 0;
+}
+/**
+ * If the given ast node is inside an explicit constructor call
+ * then wrap it with a fake constructor call.
+ * Returns the wrapped completion node or the completion node itself.
+ */
+protected ASTNode wrapWithExplicitConstructorCallIfNeeded(ASTNode ast) {
+ int selector;
+ if (ast != null && topKnownElementKind(ASSIST_PARSER) == K_SELECTOR && ast instanceof Expression &&
+ (((selector = topKnownElementInfo(ASSIST_PARSER)) == THIS_CONSTRUCTOR) ||
+ (selector == SUPER_CONSTRUCTOR))) {
+ ExplicitConstructorCall call = new ExplicitConstructorCall(ExplicitConstructorCall.This);
+ call.arguments = new Expression[] {(Expression)ast};
+ call.sourceStart = ast.sourceStart;
+ call.sourceEnd = ast.sourceEnd;
+ return call;
+ } else {
+ return ast;
+ }
+}
+protected void consumeCallExpressionWithSimpleName() {
+ int completionIndex;
+
+ /* no need to take action if not inside completed identifiers */
+ if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+ super.consumeCallExpressionWithSimpleName();
+ return;
+ }
+
+
+ int length = identifierLengthStack[identifierLengthPtr];
+ char[][] subset = identifierSubSet(completionIndex);
+ identifierLengthPtr--;
+ identifierPtr -= length;
+
+ Expression receiver = this.expressionStack[this.expressionPtr];
+ int subsetLength=0;
+ long []subsetPositions=null;
+ if (receiver instanceof SingleNameReference) {
+ SingleNameReference snr = (SingleNameReference) receiver;
+ subsetLength=1;
+ subset=new char[][]{snr.token};
+ subsetPositions=new long[]{(((long)snr.sourceStart)<<32)+snr.sourceEnd};
+ }
+ else if (receiver instanceof ThisReference)
+ {
+ ThisReference thisReference = (ThisReference) receiver;
+
+ subsetLength=1;
+ subsetLength=1;
+ subset=new char[][]{{'t','h','i','s'}};
+ subsetPositions=new long[]{ (((long)thisReference.sourceStart)<<32)+thisReference.sourceEnd};
+
+ }
+ else
+ //TODO: implement
+ throw new org.eclipse.wst.jsdt.core.UnimplementedException();
+
+ long[] positions = new long[length+subsetLength];
+ if (subsetLength>0)
+ {
+ System.arraycopy(
+ subsetPositions,
+ 0,
+ positions,
+ 0,
+ subsetLength);
+
+ }
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ subsetLength,
+ length);
+
+
+
+ /* build specific completion on name reference */
+ NameReference reference;
+ if (completionIndex == 0 && subsetLength==0) {
+ /* completion inside first identifier */
+ reference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+ } else {
+ /* completion inside subsequent identifier */
+ reference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+ }
+ reference.bits &= ~ASTNode.RestrictiveFlagMASK;
+ reference.bits |= Binding.LOCAL | Binding.FIELD;
+
+ assistNode = reference;
+ lastCheckPoint = reference.sourceEnd + 1;
+ this.expressionStack[this.expressionPtr] =reference ;
+ this.isOrphanCompletionNode = true;
+
+
+}
+protected void consumeMemberExpressionWithSimpleName() {
+ int completionIndex;
+
+ /* no need to take action if not inside completed identifiers */
+ if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+ super.consumeMemberExpressionWithSimpleName();
+ return;
+ }
+
+
+ int length = identifierLengthStack[identifierLengthPtr];
+ char[][] subset = identifierSubSet(completionIndex);
+ identifierLengthPtr--;
+ identifierPtr -= length;
+
+ Expression receiver = this.expressionStack[this.expressionPtr];
+ int subsetLength=0;
+ long []subsetPositions=null;
+ if (receiver instanceof SingleNameReference) {
+ SingleNameReference snr = (SingleNameReference) receiver;
+ subsetLength=1;
+ subset=new char[][]{snr.token};
+ subsetPositions=new long[]{(((long)snr.sourceStart)<<32)+snr.sourceEnd};
+ }
+ else if (receiver instanceof ThisReference)
+ {
+ ThisReference thisReference = (ThisReference) receiver;
+
+ subsetLength=1;
+ subsetLength=1;
+ subset=new char[][]{{'t','h','i','s'}};
+ subsetPositions=new long[]{ (((long)thisReference.sourceStart)<<32)+thisReference.sourceEnd};
+
+ }
+ else
+ //TODO: implement
+ throw new org.eclipse.wst.jsdt.core.UnimplementedException();
+
+ long[] positions = new long[length+subsetLength];
+ if (subsetLength>0)
+ {
+ System.arraycopy(
+ subsetPositions,
+ 0,
+ positions,
+ 0,
+ subsetLength);
+
+ }
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ subsetLength,
+ length);
+
+
+
+ /* build specific completion on name reference */
+ NameReference reference;
+ if (completionIndex == 0 && subsetLength==0) {
+ /* completion inside first identifier */
+ reference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+ } else {
+ /* completion inside subsequent identifier */
+ reference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+ }
+ reference.bits &= ~ASTNode.RestrictiveFlagMASK;
+ reference.bits |= Binding.LOCAL | Binding.FIELD;
+
+ assistNode = reference;
+ lastCheckPoint = reference.sourceEnd + 1;
+ this.expressionStack[this.expressionPtr] =reference ;
+ this.isOrphanCompletionNode = true;
+
+
+}
+protected void classInstanceCreation(boolean isQualified, boolean isShort) {
+ popElement(K_SELECTOR);
+ super.classInstanceCreation(isQualified, isShort);
+ AllocationExpression expression = (AllocationExpression)this.expressionStack[this.expressionPtr];
+ Expression member = expression.member;
+ if (member.isSpecialNode())
+ {
+ this.createAssistTypeForAllocation(expression);
+ }
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/Engine.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/Engine.java
new file mode 100644
index 0000000..bc96304
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/Engine.java
@@ -0,0 +1,392 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.env.IBinaryType;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ITypeRequestor;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ITypeRequestor2;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ImportBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ImportConflictBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.SourceTypeConverter;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.wst.jsdt.internal.core.NameLookup;
+import org.eclipse.wst.jsdt.internal.core.SearchableEnvironment;
+import org.eclipse.wst.jsdt.internal.oaametadata.LibraryAPIs;
+
+public abstract class Engine implements ITypeRequestor, ITypeRequestor2 {
+
+ public LookupEnvironment lookupEnvironment;
+
+ protected CompilationUnitScope unitScope;
+ public SearchableEnvironment nameEnvironment;
+
+ public AssistOptions options;
+ public CompilerOptions compilerOptions;
+ public boolean forbiddenReferenceIsError;
+ public boolean discouragedReferenceIsError;
+
+ public boolean importCachesInitialized = false;
+ public char[][][] importsCache;
+ public ImportBinding[] onDemandImportsCache;
+ public int importCacheCount = 0;
+ public int onDemandImportCacheCount = 0;
+ public char[] currentPackageName = null;
+
+ // astInUse is a map from CU to AST and keeps the AST's that is being currently used by resolving mechanism.
+ private static HashMap astInUse = new HashMap();
+
+ public Engine(Map settings){
+ this.options = new AssistOptions(settings);
+ this.compilerOptions = new CompilerOptions(settings);
+ this.forbiddenReferenceIsError =
+ (this.compilerOptions.getSeverity(CompilerOptions.ForbiddenReference) & ProblemSeverities.Error) != 0;
+ this.discouragedReferenceIsError =
+ (this.compilerOptions.getSeverity(CompilerOptions.DiscouragedReference) & ProblemSeverities.Error) != 0;
+ }
+
+ /**
+ * Add an additional binary type
+ */
+ public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+// lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
+ }
+
+ public abstract CompilationUnitDeclaration doParse(ICompilationUnit unit, AccessRestriction accessRestriction) ;
+ /**
+ * Add an additional compilation unit.
+ */
+ public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
+ CompilationUnitDeclaration parsedUnit = doParse(sourceUnit,accessRestriction);
+
+ lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
+ lookupEnvironment.completeTypeBindings(parsedUnit, true);
+ }
+
+ public void accept(ICompilationUnit unit, char[][] typeNames, AccessRestriction accessRestriction) {
+ CompilationUnitDeclaration parsedUnit;
+ boolean astAdded = false;
+ CompilationUnitScope oldScope = null;
+
+ // If the AST is already in memory(namely, it's being used for finding other bindings),
+ // use it instead of parsing again. This reduces performance problem of redundant parsing.
+ if (astInUse.containsKey(unit)) {
+ parsedUnit = (CompilationUnitDeclaration) astInUse.get(unit);
+ } else {
+ parsedUnit = doParse(unit,accessRestriction);
+ astInUse.put(unit, parsedUnit);
+ astAdded = true;
+ }
+ // keeps the scope object of parsedUnit because it will be overwritten in buildTypeBindings()
+ oldScope = parsedUnit.scope;
+
+ try {
+ lookupEnvironment.buildTypeBindings(parsedUnit, typeNames, accessRestriction);
+ lookupEnvironment.completeTypeBindings(parsedUnit, typeNames, true);
+ } finally {
+ // If the AST is added in the current frame, remove it and it'll be GC'ed.
+ if(astAdded) {
+ astInUse.remove(unit);
+ }
+ // restore scope object
+ parsedUnit.scope = oldScope;
+ }
+ }
+
+ /**
+ * Add additional source types (the first one is the requested type, the rest is formed by the
+ * secondary types defined in the same compilation unit).
+ */
+ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ CompilationResult result =
+ new CompilationResult(sourceTypes[0].getFileName(), sourceTypes[0].getPackageName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+ CompilationUnitDeclaration unit =
+ SourceTypeConverter.buildCompilationUnit(
+ sourceTypes,//sourceTypes[0] is always toplevel here
+ SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+ | SourceTypeConverter.MEMBER_TYPE, // need member types
+ // no need for field initialization
+ lookupEnvironment.problemReporter,
+ result);
+
+ if (unit != null) {
+ lookupEnvironment.buildTypeBindings(unit, accessRestriction);
+ lookupEnvironment.completeTypeBindings(unit, true);
+ }
+ }
+
+ public void accept(LibraryAPIs libraryMetaData) {
+ lookupEnvironment.buildTypeBindings(libraryMetaData);
+ }
+
+ public abstract AssistParser getParser();
+
+ public void initializeImportCaches() {
+ ImportBinding[] importBindings = this.unitScope.imports;
+ int length = importBindings == null ? 0 : importBindings.length;
+
+ this.currentPackageName = CharOperation.concatWith(new char[][] {}, '.');
+
+ for (int i = 0; i < length; i++) {
+ ImportBinding importBinding = importBindings[i];
+ if(importBinding.onDemand) {
+ if(this.onDemandImportsCache == null) {
+ this.onDemandImportsCache = new ImportBinding[length - i];
+ }
+ this.onDemandImportsCache[this.onDemandImportCacheCount++] =
+ importBinding;
+ } else {
+ if(!(importBinding.resolvedImport instanceof MethodBinding) ||
+ importBinding instanceof ImportConflictBinding) {
+ if(this.importsCache == null) {
+ this.importsCache = new char[length - i][][];
+ }
+ this.importsCache[this.importCacheCount++] = new char[][]{
+ importBinding.compoundName[importBinding.compoundName.length - 1],
+ CharOperation.concatWith(importBinding.compoundName, '.')
+ };
+ }
+ }
+ }
+
+ this.importCachesInitialized = true;
+ }
+
+ protected boolean mustQualifyType(
+ char[] packageName,
+ char[] typeName,
+ char[] enclosingTypeNames,
+ int modifiers) {
+
+ // If there are no types defined into the current CU yet.
+ if (unitScope == null)
+ return true;
+
+ if(!this.importCachesInitialized) {
+ this.initializeImportCaches();
+ }
+
+
+ for (int i = 0; i < this.importCacheCount; i++) {
+ char[][] importName = this.importsCache[i];
+ if(CharOperation.equals(typeName, importName[0])) {
+ char[] fullyQualifiedTypeName =
+ enclosingTypeNames == null || enclosingTypeNames.length == 0
+ ? CharOperation.concat(
+ packageName,
+ typeName,
+ '.')
+ : CharOperation.concat(
+ CharOperation.concat(
+ packageName,
+ enclosingTypeNames,
+ '.'),
+ typeName,
+ '.');
+ return !CharOperation.equals(fullyQualifiedTypeName, importName[1]);
+ }
+ }
+
+ if ((enclosingTypeNames == null || enclosingTypeNames.length == 0 ) && CharOperation.equals(this.currentPackageName, packageName))
+ return false;
+
+ char[] fullyQualifiedEnclosingTypeName = null;
+
+ for (int i = 0; i < this.onDemandImportCacheCount; i++) {
+ ImportBinding importBinding = this.onDemandImportsCache[i];
+ Binding resolvedImport = importBinding.resolvedImport;
+
+ char[][] importName = importBinding.compoundName;
+ char[] importFlatName = CharOperation.concatWith(importName, '.');
+
+ boolean isFound = false;
+ // resolvedImport is a ReferenceBindng or a PackageBinding
+ if(resolvedImport instanceof ReferenceBinding) {
+ if(enclosingTypeNames != null && enclosingTypeNames.length != 0) {
+ if(fullyQualifiedEnclosingTypeName == null) {
+ fullyQualifiedEnclosingTypeName =
+ CharOperation.concat(
+ packageName,
+ enclosingTypeNames,
+ '.');
+ }
+ if(CharOperation.equals(fullyQualifiedEnclosingTypeName, importFlatName)) {
+ isFound = true;
+ }
+ }
+ } else {
+ if(enclosingTypeNames == null || enclosingTypeNames.length == 0) {
+ if(CharOperation.equals(packageName, importFlatName)) {
+ isFound = true;
+ }
+ }
+ }
+
+ // find potential conflict with another import
+ if(isFound) {
+ for (int j = 0; j < this.onDemandImportCacheCount; j++) {
+ if(i != j) {
+ ImportBinding conflictingImportBinding = this.onDemandImportsCache[j];
+ if(conflictingImportBinding.resolvedImport instanceof ReferenceBinding) {
+ ReferenceBinding refBinding =
+ (ReferenceBinding) conflictingImportBinding.resolvedImport;
+ if (refBinding.getMemberType(typeName) != null) {
+ return true;
+ }
+ } else {
+ char[] conflictingImportName =
+ CharOperation.concatWith(conflictingImportBinding.compoundName, '.');
+
+ if (this.nameEnvironment.nameLookup.findType(
+ String.valueOf(typeName),
+ String.valueOf(conflictingImportName),
+ false,
+ NameLookup.ACCEPT_ALL,
+ false/*don't check restrictions*/) != null) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Find the node (a field, a method or an initializer) at the given position
+ * and parse its block statements if it is a method or an initializer.
+ * Returns the node or null if not found
+ */
+ protected ASTNode parseBlockStatements(CompilationUnitDeclaration unit, int position) {
+ int length = unit.types.length;
+ for (int i = 0; i < length; i++) {
+ TypeDeclaration type = unit.types[i];
+ if (type.declarationSourceStart < position
+ && type.declarationSourceEnd >= position) {
+ getParser().scanner.setSource(unit.compilationResult);
+ return parseBlockStatements(type, unit, position);
+ }
+ }
+ return null;
+ }
+
+ private ASTNode parseBlockStatements(
+ TypeDeclaration type,
+ CompilationUnitDeclaration unit,
+ int position) {
+ //members
+ TypeDeclaration[] memberTypes = type.memberTypes;
+ if (memberTypes != null) {
+ int length = memberTypes.length;
+ for (int i = 0; i < length; i++) {
+ TypeDeclaration memberType = memberTypes[i];
+ if (memberType.bodyStart > position)
+ continue;
+ if (memberType.declarationSourceEnd >= position) {
+ return parseBlockStatements(memberType, unit, position);
+ }
+ }
+ }
+ //methods
+ AbstractMethodDeclaration[] methods = type.methods;
+ if (methods != null) {
+ int length = methods.length;
+ for (int i = 0; i < length; i++) {
+ AbstractMethodDeclaration method = methods[i];
+ if (method.bodyStart > position)
+ continue;
+
+ if(method.isDefaultConstructor())
+ continue;
+
+ if (method.declarationSourceEnd >= position) {
+
+ getParser().parseBlockStatements(method, unit);
+ return method;
+ }
+ }
+ }
+ //initializers
+ FieldDeclaration[] fields = type.fields;
+ if (fields != null) {
+ int length = fields.length;
+ for (int i = 0; i < length; i++) {
+ FieldDeclaration field = fields[i];
+ if (field.sourceStart > position)
+ continue;
+ if (field.declarationSourceEnd >= position) {
+ if (field instanceof Initializer) {
+ getParser().parseBlockStatements((Initializer)field, type, unit);
+ }
+ return field;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected void reset() {
+ lookupEnvironment.reset();
+ }
+
+ public static char[] getTypeSignature(TypeBinding typeBinding) {
+ return typeBinding.signature();
+ }
+ public static char[] getSignature(Binding binding) {
+ char[] result = null;
+ if ((binding.kind() & Binding.TYPE) != 0 || (binding.kind() & Binding.COMPILATION_UNIT) != 0) {
+ TypeBinding typeBinding = (TypeBinding)binding;
+ result = typeBinding.signature();
+ } else if ((binding.kind() & Binding.METHOD) != 0) {
+ MethodBinding methodBinding = (MethodBinding)binding;
+ int oldMod = methodBinding.modifiers;
+ result = methodBinding.signature();
+ methodBinding.modifiers = oldMod;
+ }
+ if (result != null) {
+ if ( (binding.kind() & Binding.TYPE) != 0 )
+ result = CharOperation.replaceOnCopy(result, '/', '.');
+ }
+ return result;
+ }
+
+ public static char[][] getSignatures(Binding[] bindings) {
+ int length = bindings == null ? 0 : bindings.length;
+ char[][] signatures = new char[length][];
+ for (int i = 0; i < length; i++) {
+ signatures[i] = getSignature(bindings[i]);
+ }
+ return signatures;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/Keywords.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/Keywords.java
new file mode 100644
index 0000000..055312e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/impl/Keywords.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.impl;
+
+public interface Keywords {
+ int COUNT = 48;
+
+ char[] ABSTRACT = "abstract".toCharArray(); //$NON-NLS-1$
+ char[] ASSERT = "assert".toCharArray(); //$NON-NLS-1$
+ char[] BREAK = "break".toCharArray(); //$NON-NLS-1$
+ char[] CASE = "case".toCharArray(); //$NON-NLS-1$
+ char[] CATCH = "catch".toCharArray(); //$NON-NLS-1$
+ char[] CLASS = "class".toCharArray(); //$NON-NLS-1$
+ char[] CONTINUE = "continue".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT = "default".toCharArray(); //$NON-NLS-1$
+ char[] DO = "do".toCharArray(); //$NON-NLS-1$
+ char[] ELSE = "else".toCharArray(); //$NON-NLS-1$
+ char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$
+ char[] FINAL = "final".toCharArray(); //$NON-NLS-1$
+ char[] FINALLY = "finally".toCharArray(); //$NON-NLS-1$
+ char[] FOR = "for".toCharArray(); //$NON-NLS-1$
+ char[] IF = "if".toCharArray(); //$NON-NLS-1$
+ char[] IMPLEMENTS = "implements".toCharArray(); //$NON-NLS-1$
+ char[] IMPORT = "import".toCharArray(); //$NON-NLS-1$
+ char[] INSTANCEOF = "instanceof".toCharArray(); //$NON-NLS-1$
+ char[] INTERFACE = "interface".toCharArray(); //$NON-NLS-1$
+ char[] NATIVE = "native".toCharArray(); //$NON-NLS-1$
+ char[] NEW = "new".toCharArray(); //$NON-NLS-1$
+ char[] PACKAGE = "package".toCharArray(); //$NON-NLS-1$
+ char[] PRIVATE = "private".toCharArray(); //$NON-NLS-1$
+ char[] PROTECTED = "protected".toCharArray(); //$NON-NLS-1$
+ char[] PUBLIC = "public".toCharArray(); //$NON-NLS-1$
+ char[] RETURN = "return".toCharArray(); //$NON-NLS-1$
+ char[] STATIC = "static".toCharArray(); //$NON-NLS-1$
+ char[] STRICTFP = "strictfp".toCharArray(); //$NON-NLS-1$
+ char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
+ char[] SWITCH = "switch".toCharArray(); //$NON-NLS-1$
+ char[] SYNCHRONIZED = "synchronized".toCharArray(); //$NON-NLS-1$
+ char[] THIS = "this".toCharArray(); //$NON-NLS-1$
+ char[] THROW = "throw".toCharArray(); //$NON-NLS-1$
+ char[] THROWS = "throws".toCharArray(); //$NON-NLS-1$
+ char[] TRANSIENT = "transient".toCharArray(); //$NON-NLS-1$
+ char[] TRY = "try".toCharArray(); //$NON-NLS-1$
+ char[] VOLATILE = "volatile".toCharArray(); //$NON-NLS-1$
+ char[] WHILE = "while".toCharArray(); //$NON-NLS-1$
+ char[] TRUE = "true".toCharArray(); //$NON-NLS-1$
+ char[] FALSE = "false".toCharArray(); //$NON-NLS-1$
+ char[] NULL = "null".toCharArray(); //$NON-NLS-1$
+ char[] VAR = "var".toCharArray(); //$NON-NLS-1$
+ char[] FUNCTION = "function".toCharArray(); //$NON-NLS-1$
+ char[] UNDEFINED = "undefined".toCharArray(); //$NON-NLS-1$
+ char[] DELETE = "delete".toCharArray(); //$NON-NLS-1$
+ char[] TYPEOF = "typeof".toCharArray(); //$NON-NLS-1$
+ char[] WITH = "with".toCharArray(); //$NON-NLS-1$
+ char[] IN = "in".toCharArray(); //$NON-NLS-1$
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionJavadoc.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionJavadoc.java
new file mode 100644
index 0000000..ca2e1ec
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionJavadoc.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+
+/**
+ * Node representing a Javadoc comment including code selection.
+ */
+public class SelectionJavadoc extends Javadoc {
+
+ Expression selectedNode;
+
+ public SelectionJavadoc(int sourceStart, int sourceEnd) {
+ super(sourceStart, sourceEnd);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc#print(int, java.lang.StringBuffer)
+ */
+ public StringBuffer print(int indent, StringBuffer output) {
+ super.print(indent, output);
+ if (this.selectedNode != null) {
+ String selectedString = null;
+ if (this.selectedNode instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) this.selectedNode;
+ if (fieldRef.methodBinding != null) {
+ selectedString = "');
+ }
+ return output;
+ }
+
+ /**
+ * Resolve selected node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws SelectionNodeFound
+ */
+ private void internalResolve(Scope scope) {
+ if (this.selectedNode != null) {
+ switch (scope.kind) {
+ case Scope.CLASS_SCOPE:
+ this.selectedNode.resolveType((ClassScope)scope);
+ break;
+ case Scope.METHOD_SCOPE:
+ this.selectedNode.resolveType((MethodScope)scope);
+ break;
+ }
+ Binding binding = null;
+ if (this.selectedNode instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) this.selectedNode;
+ binding = fieldRef.binding;
+ if (binding == null && fieldRef.methodBinding != null) {
+ binding = fieldRef.methodBinding;
+ }
+ } else if (this.selectedNode instanceof JavadocMessageSend) {
+ binding = ((JavadocMessageSend) this.selectedNode).binding;
+ } else if (this.selectedNode instanceof JavadocAllocationExpression) {
+ binding = ((JavadocAllocationExpression) this.selectedNode).binding;
+ } else if (this.selectedNode instanceof JavadocSingleNameReference) {
+ binding = ((JavadocSingleNameReference) this.selectedNode).binding;
+ } else if (this.selectedNode instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) this.selectedNode;
+ if (typeRef.packageBinding == null) {
+ binding = typeRef.resolvedType;
+ }
+ } else if (this.selectedNode instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) this.selectedNode;
+ if (typeRef.packageBinding == null) {
+ binding = typeRef.resolvedType;
+ }
+ } else {
+ binding = this.selectedNode.resolvedType;
+ }
+ throw new SelectionNodeFound(binding);
+ }
+ }
+
+ /**
+ * Resolve selected node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws SelectionNodeFound
+ */
+ public void resolve(ClassScope scope) {
+ internalResolve(scope);
+ }
+
+ /**
+ * Resolve selected node if not null and throw exception to let clients know
+ * that it has been found.
+ *
+ * @throws SelectionNodeFound
+ */
+ public void resolve(MethodScope scope) {
+ internalResolve(scope);
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionJavadocParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionJavadocParser.java
new file mode 100644
index 0000000..6bc32ef
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionJavadocParser.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
+import org.eclipse.wst.jsdt.internal.codeassist.SelectionEngine;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocParser;
+
+/**
+ * Parser specialized for decoding javadoc comments which includes code selection.
+ */
+public class SelectionJavadocParser extends JavadocParser {
+
+ int selectionStart;
+ int selectionEnd;
+ ASTNode selectedNode;
+
+ public SelectionJavadocParser(SelectionParser sourceParser) {
+ super(sourceParser);
+ this.kind = SELECTION_PARSER | TEXT_PARSE;
+ }
+
+ /*
+ * Do not parse comment if selection is not included.
+ */
+ public boolean checkDeprecation(int commentPtr) {
+ this.selectionStart = ((SelectionParser)sourceParser).selectionStart;
+ this.selectionEnd = ((SelectionParser)sourceParser).selectionEnd;
+ this.javadocStart = this.sourceParser.scanner.commentStarts[commentPtr];
+ this.javadocEnd = this.sourceParser.scanner.commentStops[commentPtr];
+ if (this.javadocStart <= this.selectionStart && this.selectionEnd <= this.javadocEnd) {
+ if (SelectionEngine.DEBUG) {
+ System.out.println("SELECTION in Javadoc:"); //$NON-NLS-1$
+ }
+ super.checkDeprecation(commentPtr);
+ } else {
+ this.docComment = null;
+ }
+ return false;
+ }
+
+ /*
+ * Replace stored Javadoc node with specific selection one.
+ */
+ protected boolean commentParse() {
+ this.docComment = new SelectionJavadoc(this.javadocStart, this.javadocEnd);
+ return super.commentParse();
+ }
+
+ /*
+ * Create argument expression and store it if it includes selection.
+ */
+ protected Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException {
+ // Create argument as we may need it after
+ Expression expression = (Expression) super.createArgumentReference(name, dim, isVarargs, typeRef, dimPositions, argNamePos);
+ // See if selection is in argument
+ int start = ((TypeReference)typeRef).sourceStart;
+ int end = ((TypeReference)typeRef).sourceEnd;
+ if (start <= this.selectionStart && this.selectionEnd <= end) {
+ selectedNode = expression;
+ this.abort = true;
+ if (SelectionEngine.DEBUG) {
+ System.out.println(" selected argument="+selectedNode); //$NON-NLS-1$
+ }
+ }
+ return expression;
+ }
+
+ /*
+ * Verify if field identifier positions include selection.
+ * If so, create field reference, store it and abort comment parse.
+ * Otherwise return null as we do not need this reference.
+ */
+ protected Object createFieldReference(Object receiver) throws InvalidInputException {
+ int start = (int) (this.identifierPositionStack[0] >>> 32);
+ int end = (int) this.identifierPositionStack[0];
+ if (start <= this.selectionStart && this.selectionEnd <= end) {
+ selectedNode = (ASTNode) super.createFieldReference(receiver);
+ this.abort = true;
+ if (SelectionEngine.DEBUG) {
+ System.out.println(" selected field="+selectedNode); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Verify if method identifier positions include selection.
+ * If so, create field reference, store it and abort comment parse.
+ * Otherwise return null as we do not need this reference.
+ */
+ protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException {
+ int memberPtr = this.identifierLengthStack[0] - 1; // may be > 0 for inner class constructor reference
+ int start = (int) (this.identifierPositionStack[memberPtr] >>> 32);
+ int end = (int) this.identifierPositionStack[memberPtr];
+ if (start <= this.selectionStart && this.selectionEnd <= end) {
+ selectedNode = (ASTNode) super.createMethodReference(receiver, arguments);
+ this.abort = true;
+ if (SelectionEngine.DEBUG) {
+ System.out.println(" selected method="+selectedNode); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Create type reference and verify if it includes selection.
+ * If so, store it and abort comment parse.
+ * Otherwise return null as we do not need this reference.
+ */
+ protected Object createTypeReference(int primitiveToken) {
+ // Need to create type ref in case it was needed by members
+ TypeReference typeRef = (TypeReference) super.createTypeReference(primitiveToken);
+
+ // See if node is concerned by selection
+ if (typeRef.sourceStart <= this.selectionStart && this.selectionEnd <= typeRef.sourceEnd) {
+ // See if selection is in one of tokens of qualification
+ if (typeRef instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference qualifiedTypeRef = (JavadocQualifiedTypeReference) typeRef;
+ int size = qualifiedTypeRef.tokens.length - 1;
+ for (int i=0; i>> 32);
+ int end = (int) qualifiedTypeRef.sourcePositions[i];
+ if (start <= this.selectionStart && this.selectionEnd <= end) {
+ int pos = i + 1;
+ char[][] tokens = new char[pos][];
+ int ptr = this.identifierPtr - size;
+ System.arraycopy(this.identifierStack, ptr, tokens, 0, pos);
+ long[] positions = new long[pos];
+ System.arraycopy(this.identifierPositionStack, ptr, positions, 0, pos);
+ selectedNode = new JavadocQualifiedTypeReference(tokens, positions, this.tagSourceStart, this.tagSourceEnd);
+ this.abort = true; // we got selected node => cancel parse
+ if (SelectionEngine.DEBUG) {
+ System.out.println(" selected partial qualified type="+selectedNode); //$NON-NLS-1$
+ }
+ return typeRef;
+ }
+ }
+ // Selection is in last token => we'll store type ref as this
+ }
+ // Store type ref as selected node
+ selectedNode = typeRef;
+ this.abort = true; // we got selected node => cancel parse
+ if (SelectionEngine.DEBUG) {
+ System.out.println(" selected type="+selectedNode); //$NON-NLS-1$
+ }
+ }
+ return typeRef;
+ }
+
+ /*
+ * Push param reference and verify if it includes selection.
+ * If so, store it and abort comment parse.
+ */
+ protected boolean pushParamName(boolean isTypeParam) {
+ if (super.pushParamName(isTypeParam)) {
+ Expression expression = (Expression) astStack[astPtr--];
+ // See if expression is concerned by selection
+ if (expression.sourceStart <= this.selectionStart && this.selectionEnd <= expression.sourceEnd) {
+ selectedNode = expression;
+ this.abort = true; // we got selected node => cancel parse
+ if (SelectionEngine.DEBUG) {
+ System.out.println(" selected param="+selectedNode); //$NON-NLS-1$
+ }
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Store selected node into doc comment.
+ */
+ protected void updateDocComment() {
+ if (selectedNode instanceof Expression) {
+ ((SelectionJavadoc) this.docComment).selectedNode = (Expression) selectedNode;
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionNodeFound.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionNodeFound.java
new file mode 100644
index 0000000..f535e8a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionNodeFound.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+
+public class SelectionNodeFound extends RuntimeException {
+
+ public Binding binding;
+ public boolean isDeclaration;
+ private static final long serialVersionUID = -7335444736618092295L; // backward compatible
+
+public SelectionNodeFound() {
+ this(null, false); // we found a problem in the selection node
+}
+public SelectionNodeFound(Binding binding) {
+ this(binding, false);
+}
+public SelectionNodeFound(Binding binding, boolean isDeclaration) {
+ this.binding = binding;
+ this.isDeclaration = isDeclaration;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnArgumentName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnArgumentName.java
new file mode 100644
index 0000000..f3f6e82
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnArgumentName.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnArgumentName extends Argument {
+
+ public SelectionOnArgumentName(char[] name , long posNom , TypeReference tr , int modifiers){
+
+ super(name, posNom, tr, modifiers);
+ }
+
+ public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+
+ super.bind(scope, typeBinding, used);
+ throw new SelectionNodeFound(binding);
+ }
+
+ public StringBuffer print(int indent, StringBuffer output) {
+
+ printIndent(indent, output);
+ output.append("');
+ }
+
+ public void resolve(BlockScope scope) {
+
+ super.resolve(scope);
+ throw new SelectionNodeFound(binding);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java
new file mode 100644
index 0000000..b785def
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an explicit constructor call containing the cursor.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * Y.[start]super[end](1, 2)
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+
+public class SelectionOnExplicitConstructorCall extends ExplicitConstructorCall {
+
+ public SelectionOnExplicitConstructorCall(int accessMode) {
+
+ super(accessMode);
+ }
+
+ public StringBuffer printStatement(int tab, StringBuffer output) {
+
+ printIndent(tab, output);
+ output.append(" 0) output.append(", "); //$NON-NLS-1$
+ arguments[i].printExpression(0, output);
+ }
+ }
+ return output.append(")>;"); //$NON-NLS-1$
+ }
+
+ public void resolve(BlockScope scope) {
+
+ super.resolve(scope);
+
+ // tolerate some error cases
+ if (binding == null ||
+ !(binding.isValidBinding() ||
+ binding.problemId() == ProblemReasons.NotVisible))
+ throw new SelectionNodeFound();
+ else
+ throw new SelectionNodeFound(binding);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnFieldReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnFieldReference.java
new file mode 100644
index 0000000..185e19c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnFieldReference.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a field reference containing the cursor.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * bar().[start]fred[end]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnFieldReference extends FieldReference {
+
+ public SelectionOnFieldReference(char[] source , long pos) {
+
+ super(source, pos);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output){
+
+ output.append("');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ super.resolveType(scope);
+ // tolerate some error cases
+ if (binding == null ||
+ !(binding.isValidBinding() ||
+ binding.problemId() == ProblemReasons.NotVisible
+ || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext))
+ throw new SelectionNodeFound();
+ else
+ throw new SelectionNodeFound(binding);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnFieldType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnFieldType.java
new file mode 100644
index 0000000..a244765
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnFieldType.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+
+public class SelectionOnFieldType extends FieldDeclaration {
+ public SelectionOnFieldType(TypeReference type) {
+ super();
+ this.sourceStart = type.sourceStart;
+ this.sourceEnd = type.sourceEnd;
+ this.type = type;
+ this.name = CharOperation.NO_CHAR;
+ }
+ public StringBuffer printStatement(int tab, StringBuffer output) {
+ return type.print(tab, output).append(';');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnImportReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnImportReference.java
new file mode 100644
index 0000000..81d23a0
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnImportReference.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an import reference containing the assist identifier.
+ * e.g.
+ *
+ * import java.[start]io[end].*;
+ * class X {
+ * void foo() {
+ * }
+ * }
+ *
+ * --->
+ * class X {
+ * void foo() {
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+
+public class SelectionOnImportReference extends ImportReference {
+
+public SelectionOnImportReference(char[][] tokens , long[] positions) {
+ super(tokens, positions, false);
+}
+public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
+
+ printIndent(indent, output).append(" 0) output.append('.');
+ output.append(tokens[i]);
+ }
+ return output.append('>');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnLocalName.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnLocalName.java
new file mode 100644
index 0000000..4065e3d
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnLocalName.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+public class SelectionOnLocalName extends LocalDeclaration{
+
+ public SelectionOnLocalName(char[] name, int sourceStart, int sourceEnd) {
+
+ super(name, sourceStart, sourceEnd);
+ }
+
+ public void resolve(BlockScope scope) {
+
+ super.resolve(scope);
+ throw new SelectionNodeFound(binding);
+ }
+
+ public StringBuffer printAsExpression(int indent, StringBuffer output) {
+ printIndent(indent, output);
+ output.append("');
+ }
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+ this.printAsExpression(indent, output);
+ return output.append(';');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnMessageSend.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnMessageSend.java
new file mode 100644
index 0000000..b4d14b1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnMessageSend.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a message send containing the cursor.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * this.[start]bar[end](1, 2)
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnMessageSend extends MessageSend {
+
+ /*
+ * Cannot answer default abstract match, iterate in superinterfaces of declaring class
+ * for a better match (default abstract match came from scope lookups).
+ */
+ private MethodBinding findNonDefaultAbstractMethod(MethodBinding methodBinding) {
+ return methodBinding;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append(" 0) output.append(", "); //$NON-NLS-1$
+ arguments[i].printExpression(0, output);
+ }
+ }
+ return output.append(")>"); //$NON-NLS-1$
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ super.resolveType(scope);
+
+ // tolerate some error cases
+ if(binding == null ||
+ !(binding.isValidBinding() ||
+ binding.problemId() == ProblemReasons.NotVisible
+ || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext)) {
+ throw new SelectionNodeFound();
+ } else {
+ if(binding.isDefaultAbstract()) {
+ throw new SelectionNodeFound(findNonDefaultAbstractMethod(binding)); // 23594
+ } else {
+ throw new SelectionNodeFound(binding);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnPackageReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnPackageReference.java
new file mode 100644
index 0000000..ded889c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnPackageReference.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an package statement containing the assist identifier.
+ * e.g.
+ *
+ * package java.[start]io[end];
+ * class X {
+ * void foo() {
+ * }
+ * }
+ *
+ * --->
+ * class X {
+ * void foo() {
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+
+public class SelectionOnPackageReference extends ImportReference {
+public SelectionOnPackageReference(char[][] tokens , long[] positions) {
+ super(tokens, positions, true);
+}
+public StringBuffer print(int tab, StringBuffer output, boolean withOnDemand) {
+ printIndent(tab, output).append(" 0) output.append('.');
+ output.append(tokens[i]);
+ }
+ return output.append('>');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
new file mode 100644
index 0000000..e063dbb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an allocation expression containing the cursor.
+ * If the allocation expression is not qualified, the enclosingInstance field
+ * is null.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * new [start]Bar[end](1, 2)
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnQualifiedAllocationExpression extends QualifiedAllocationExpression {
+
+ public SelectionOnQualifiedAllocationExpression() {
+ // constructor without argument
+ }
+
+ public SelectionOnQualifiedAllocationExpression(TypeDeclaration anonymous) {
+ super(anonymous);
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ if (this.enclosingInstance == null)
+ output.append("');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ super.resolveType(scope);
+
+ // tolerate some error cases
+ if (binding == null ||
+ !(binding.isValidBinding() ||
+ binding.problemId() == ProblemReasons.NotVisible))
+ throw new SelectionNodeFound();
+ if (anonymousType == null)
+ throw new SelectionNodeFound(binding);
+
+ // if selecting a type for an anonymous type creation, we have to
+ // find its target super constructor (if extending a class) or its target
+ // super interface (if extending an interface)
+ // find the constructor binding inside the super constructor call
+ ConstructorDeclaration constructor = (ConstructorDeclaration) anonymousType.declarationOf(binding.original());
+ throw new SelectionNodeFound(constructor.constructorCall.binding);
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java
new file mode 100644
index 0000000..9c01363
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a qualified name reference containing the assist identifier.
+ * e.g.
+ *
+ * class X {
+ * Y y;
+ * void foo() {
+ * y.fred.[start]ba[end]
+ * }
+ * }
+ *
+ * ---> class X {
+ * Y y;
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnQualifiedNameReference extends QualifiedNameReference {
+
+public SelectionOnQualifiedNameReference(char[][] previousIdentifiers, char[] selectionIdentifier, long[] positions) {
+ super(
+ CharOperation.arrayConcat(previousIdentifiers, selectionIdentifier),
+ positions,
+ (int) (positions[0] >>> 32),
+ (int) positions[positions.length - 1]);
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append(" 0) output.append('.');
+ output.append(tokens[i]);
+ }
+ return output.append('>');
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // it can be a package, type, member type, local variable or field
+ binding = scope.getBinding(tokens, this);
+ if (!binding.isValidBinding()) {
+ if (binding instanceof ProblemFieldBinding) {
+ // tolerate some error cases
+ if (binding.problemId() == ProblemReasons.NotVisible
+ || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext) {
+ throw new SelectionNodeFound(binding);
+ }
+ scope.problemReporter().invalidField(this, (FieldBinding) binding);
+ } else if (binding instanceof ProblemReferenceBinding) {
+ // tolerate some error cases
+ if (binding.problemId() == ProblemReasons.NotVisible){
+ throw new SelectionNodeFound(binding);
+ }
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ } else {
+ scope.problemReporter().unresolvableReference(this, binding);
+ }
+ throw new SelectionNodeFound();
+ }
+ throw new SelectionNodeFound(binding);
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedType.java
new file mode 100644
index 0000000..6e2cc3b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedType.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+public class SelectionOnQualifiedType extends SelectionOnQualifiedNameReference {
+
+ public SelectionOnQualifiedType(char[][] previousIdentifiers, char[] selectionIdentifier, long[] positions) {
+ super(previousIdentifiers, selectionIdentifier, positions);
+ }
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append(" 0) output.append('.');
+ output.append(tokens[i]);
+ }
+ return output.append('>');
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
new file mode 100644
index 0000000..89bf5d9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as part
+ * of a qualified name.
+ * e.g.
+ *
+ * class X extends java.lang.[start]Object[end]
+ *
+ * ---> class X extends
+ *
+ */
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnQualifiedTypeReference extends QualifiedTypeReference {
+public SelectionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] selectionIdentifier, long[] positions) {
+ super(
+ CharOperation.arrayConcat(previousIdentifiers, selectionIdentifier),
+ positions);
+}
+public void aboutToResolve(Scope scope) {
+ getTypeBinding(scope.parent); // step up from the ClassScope
+}
+protected TypeBinding getTypeBinding(Scope scope) {
+ // it can be a package, type or member type
+ Binding binding = scope.getTypeOrPackage(tokens);
+ if (!binding.isValidBinding()) {
+ // tolerate some error cases
+ if (binding.problemId() == ProblemReasons.NotVisible){
+ throw new SelectionNodeFound(binding);
+ }
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ throw new SelectionNodeFound();
+ }
+
+ throw new SelectionNodeFound(binding);
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append(" 0) output.append('.');
+ output.append(tokens[i]);
+ }
+ return output.append('>');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleNameReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleNameReference.java
new file mode 100644
index 0000000..de19843
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleNameReference.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a single name reference containing the assist identifier.
+ * e.g.
+ *
+ * class X {
+ * void foo() {
+ * [start]ba[end]
+ * }
+ * }
+ *
+ * ---> class X {
+ * void foo() {
+ *
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemFieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnSingleNameReference extends SingleNameReference {
+public SelectionOnSingleNameReference(char[] source, long pos) {
+ super(source, pos);
+}
+public TypeBinding resolveType(BlockScope scope) {
+ if (this.actualReceiverType != null) {
+ this.binding = scope.getField(this.actualReceiverType, token, this);
+ if (this.binding != null && this.binding.isValidBinding()) {
+ throw new SelectionNodeFound(binding);
+ }
+ }
+ // it can be a package, type, member type, local variable or field
+ binding = scope.getBinding(token, Binding.VARIABLE | Binding.METHOD, this, true /*resolve*/);
+ if (!binding.isValidBinding()) {
+ if (binding instanceof ProblemFieldBinding) {
+ // tolerate some error cases
+ if (binding.problemId() == ProblemReasons.NotVisible
+ || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+ || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext){
+ throw new SelectionNodeFound(binding);
+ }
+ scope.problemReporter().invalidField(this, (FieldBinding) binding);
+ } else if (binding instanceof ProblemReferenceBinding) {
+ // tolerate some error cases
+ if (binding.problemId() == ProblemReasons.NotVisible){
+ throw new SelectionNodeFound(binding);
+ }
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ } else {
+ scope.problemReporter().unresolvableReference(this, binding);
+ }
+ throw new SelectionNodeFound();
+ }
+
+ throw new SelectionNodeFound(binding);
+}
+
+public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) {
+ TypeBinding typeBinding=null;
+ this.binding=
+ scope.getBinding(this.token, (Binding.TYPE|Binding.METHOD | bits) & RestrictiveFlagMASK, this, true /*resolve*/);
+ if (binding instanceof TypeBinding)
+ typeBinding=(TypeBinding)binding;
+ else if (binding instanceof MethodBinding)
+ typeBinding=((MethodBinding)binding).returnType;
+ else
+ if (typeBinding==null || binding==null)
+ throw new SelectionNodeFound();
+ else if (!binding.isValidBinding()){
+ switch (binding.problemId() ) {
+ case ProblemReasons.NotVisible:
+ case ProblemReasons.InheritedNameHidesEnclosingName:
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation:
+ case ProblemReasons.NonStaticReferenceInStaticContext:
+ throw new SelectionNodeFound(typeBinding);
+
+ default:
+ throw new SelectionNodeFound();
+ }
+// !binding.isValidBinding())
+ }
+
+ throw new SelectionNodeFound(typeBinding);
+}
+
+public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append("');
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleType.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleType.java
new file mode 100644
index 0000000..7b61955
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleType.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+public class SelectionOnSingleType extends SelectionOnSingleNameReference {
+
+ public SelectionOnSingleType(char[] source, long pos) {
+ super(source, pos);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
new file mode 100644
index 0000000..ed6e7cb
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a type reference containing the selection identifier as a single
+ * name reference.
+ * e.g.
+ *
+ * class X extends [start]Object[end]
+ *
+ * ---> class X extends
+ *
+ */
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnSingleTypeReference extends SingleTypeReference {
+public SelectionOnSingleTypeReference(char[] source, long pos) {
+ super(source, pos);
+}
+public void aboutToResolve(Scope scope) {
+ getTypeBinding(scope.parent); // step up from the ClassScope
+}
+protected TypeBinding getTypeBinding(Scope scope) {
+ // it can be a package, type or member type
+ Binding binding = scope.getTypeOrPackage(new char[][] {token});
+ if (!binding.isValidBinding()) {
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ throw new SelectionNodeFound();
+ }
+ throw new SelectionNodeFound(binding);
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ return output.append("');//$NON-NLS-1$
+}
+public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+ super.resolveTypeEnclosing(scope, enclosingType);
+
+ // tolerate some error cases
+ if (this.resolvedType == null ||
+ !(this.resolvedType.isValidBinding() ||
+ this.resolvedType.problemId() == ProblemReasons.NotVisible))
+ throw new SelectionNodeFound();
+ else
+ throw new SelectionNodeFound(this.resolvedType);
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSuperReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSuperReference.java
new file mode 100644
index 0000000..6d007a9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionOnSuperReference.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a super reference containing the assist identifier.
+ * e.g.
+ *
+ * class X extends Z {
+ * class Y {
+ * void foo() {
+ * [start]super[end].bar();
+ * }
+ * }
+ * }
+ *
+ * ---> class X {
+ * class Y {
+ * void foo() {
+ *
+ * }
+ * }
+ * }
+ *
+ */
+
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnSuperReference extends SuperReference {
+
+public SelectionOnSuperReference(int pos, int sourceEnd) {
+ super(pos, sourceEnd);
+}
+public StringBuffer printExpression(int indent, StringBuffer output){
+
+ output.append("');
+}
+public TypeBinding resolveType(BlockScope scope) {
+ TypeBinding binding = super.resolveType(scope);
+
+ if (binding == null || !binding.isValidBinding())
+ throw new SelectionNodeFound();
+ else
+ throw new SelectionNodeFound(binding);
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionParser.java
new file mode 100644
index 0000000..94ed1e9
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionParser.java
@@ -0,0 +1,690 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ * -1 means completion at the very beginning of the source
+ * 0 means completion behind the first character
+ * n means completion behind the n-th character
+ */
+
+
+import org.eclipse.wst.jsdt.internal.codeassist.impl.AssistParser;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Statement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocParser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveredType;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+public class SelectionParser extends AssistParser {
+ // OWNER
+ protected static final int SELECTION_PARSER = 1024;
+ protected static final int SELECTION_OR_ASSIST_PARSER = ASSIST_PARSER + SELECTION_PARSER;
+
+ // KIND : all values known by SelectionParser are between 1025 and 1549
+ protected static final int K_BETWEEN_CASE_AND_COLON = SELECTION_PARSER + 1; // whether we are inside a block
+
+ public ASTNode assistNodeParent; // the parent node of assist node
+
+ /* public fields */
+
+ public int selectionStart, selectionEnd;
+
+ public static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$
+
+public SelectionParser(ProblemReporter problemReporter) {
+ super(problemReporter);
+ this.javadocParser.checkDocComment = true;
+}
+public char[] assistIdentifier(){
+ return ((SelectionScanner)scanner).selectionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+ if (isOrphanCompletionNode){
+ ASTNode orphan = this.assistNode;
+ isOrphanCompletionNode = false;
+
+
+ /* if in context of a type, then persists the identifier into a fake field return type */
+ if (currentElement instanceof RecoveredType){
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (recoveredType.foundOpeningBrace) {
+ /* generate a pseudo field with a completion on type reference */
+ if (orphan instanceof TypeReference){
+ currentElement = currentElement.add(new SelectionOnFieldType((TypeReference)orphan), 0);
+ return;
+ }
+ }
+ }
+
+ if (orphan instanceof Expression) {
+ buildMoreCompletionContext((Expression)orphan);
+ } else {
+ Statement statement = (Statement) orphan;
+ currentElement = currentElement.add(statement, 0);
+ }
+ currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
+ }
+}
+private void buildMoreCompletionContext(Expression expression) {
+ ASTNode parentNode = null;
+
+ int kind = topKnownElementKind(SELECTION_OR_ASSIST_PARSER);
+ if(kind != 0) {
+// int info = topKnownElementInfo(SELECTION_OR_ASSIST_PARSER);
+ switch (kind) {
+ case K_BETWEEN_CASE_AND_COLON :
+ if(this.expressionPtr > 0) {
+ SwitchStatement switchStatement = new SwitchStatement();
+ switchStatement.expression = this.expressionStack[this.expressionPtr - 1];
+ if(this.astLengthPtr > -1 && this.astPtr > -1) {
+ int length = this.astLengthStack[this.astLengthPtr];
+ int newAstPtr = this.astPtr - length;
+ ASTNode firstNode = this.astStack[newAstPtr + 1];
+ if(length != 0 && firstNode.sourceStart > switchStatement.expression.sourceEnd) {
+ switchStatement.statements = new Statement[length + 1];
+ System.arraycopy(
+ this.astStack,
+ newAstPtr + 1,
+ switchStatement.statements,
+ 0,
+ length);
+ }
+ }
+ CaseStatement caseStatement = new CaseStatement(expression, expression.sourceStart, expression.sourceEnd);
+ if(switchStatement.statements == null) {
+ switchStatement.statements = new Statement[]{caseStatement};
+ } else {
+ switchStatement.statements[switchStatement.statements.length - 1] = caseStatement;
+ }
+ parentNode = switchStatement;
+ this.assistNodeParent = parentNode;
+ }
+ break;
+ }
+ }
+ if(parentNode != null) {
+ currentElement = currentElement.add((Statement)parentNode, 0);
+ } else {
+ currentElement = currentElement.add((Statement)wrapWithExplicitConstructorCallIfNeeded(expression), 0);
+ if(lastCheckPoint < expression.sourceEnd) {
+ lastCheckPoint = expression.sourceEnd + 1;
+ }
+ }
+}
+private boolean checkRecoveredType() {
+ if (currentElement instanceof RecoveredType){
+ /* check if current awaiting identifier is the completion identifier */
+ if (this.indexOfAssistIdentifier() < 0) return false;
+
+ if ((lastErrorEndPosition >= selectionStart)
+ && (lastErrorEndPosition <= selectionEnd+1)){
+ return false;
+ }
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ /* filter out cases where scanner is still inside type header */
+ if (recoveredType.foundOpeningBrace) {
+ this.assistNode = this.getTypeReference(0);
+ this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+ this.isOrphanCompletionNode = true;
+ return true;
+ }
+ }
+ return false;
+}
+protected void classInstanceCreation(boolean hasClassBody, boolean isShort) {
+
+ // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+ // ClassBodyopt produces a null item on the astStak if it produces NO class body
+ // An empty class body produces a 0 on the length stack.....
+
+
+// if ((astLengthStack[astLengthPtr] == 1)
+// && (astStack[astPtr] == null)) {
+
+
+// int index;
+ int argsLength= isShort ? 0 : expressionLengthStack[expressionLengthPtr];
+ if (!(this.expressionStack[this.expressionPtr-argsLength] instanceof SelectionOnSingleNameReference))
+ {
+//
+//
+// if ((index = this.indexOfAssistIdentifier()) < 0) {
+// super.classInstanceCreation(hasClassBody, isShort);
+// return;
+// } else if(this.identifierLengthPtr > -1 &&
+// (this.identifierLengthStack[this.identifierLengthPtr] - 1) != index) {
+ super.classInstanceCreation(hasClassBody, isShort);
+ return;
+ }
+ QualifiedAllocationExpression alloc;
+// astPtr--;
+// astLengthPtr--;
+ alloc = new SelectionOnQualifiedAllocationExpression();
+ alloc.sourceEnd = endPosition; //the position has been stored explicitly
+
+ if (!isShort)
+ {
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ alloc.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ }
+ else
+ alloc.arguments=new Expression[0];
+ // trick to avoid creating a selection on type reference
+ char [] oldIdent = this.assistIdentifier();
+ this.setAssistIdentifier(null);
+// alloc.type = getTypeReference(0);
+ alloc.member = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+
+ this.setAssistIdentifier(oldIdent);
+
+ //the default constructor with the correct number of argument
+ //will be created and added by the TC (see createsInternalConstructorWithBinding)
+ alloc.sourceStart = intStack[intPtr--];
+ pushOnExpressionStack(alloc);
+
+ this.assistNode = alloc;
+ this.lastCheckPoint = alloc.sourceEnd + 1;
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+ this.isOrphanCompletionNode = true;
+// } else {
+// super.classInstanceCreation(hasClassBody, isShort);
+// }
+}
+protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ // do nothing by default
+
+ super.consumeEnterVariable();
+
+// AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+// if (variable.type == assistNode){
+// if (!diet){
+// this.restartRecovery = true; // force to restart in recovery mode
+// this.lastIgnoredToken = -1;
+// }
+// isOrphanCompletionNode = false; // already attached inside variable decl
+// }
+}
+
+protected void consumeExitVariableWithInitialization() {
+ super.consumeExitVariableWithInitialization();
+
+ // does not keep the initialization if selection is not inside
+ AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+ int start = variable.initialization.sourceStart;
+ int end = variable.initialization.sourceEnd;
+ if ((selectionStart < start) && (selectionEnd < start) ||
+ (selectionStart > end) && (selectionEnd > end)) {
+ if (STOP_AT_CURSOR)
+ variable.initialization = null;
+ }
+
+}
+protected void consumeCallExpressionWithSimpleName() {
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeCallExpressionWithSimpleName();
+ return;
+ }
+ FieldReference fieldReference =
+ new SelectionOnFieldReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ identifierLengthPtr--;
+ if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
+ fieldReference.sourceStart = fieldReference.receiver.sourceStart;
+ }
+ expressionStack[expressionPtr] = fieldReference;
+ assistNode = fieldReference;
+ this.lastCheckPoint = fieldReference.sourceEnd + 1;
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+ this.isOrphanCompletionNode = true;
+
+}
+protected void consumeMemberExpressionWithSimpleName() {
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeMemberExpressionWithSimpleName();
+ return;
+ }
+ FieldReference fieldReference =
+ new SelectionOnFieldReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ identifierLengthPtr--;
+ if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
+ fieldReference.sourceStart = fieldReference.receiver.sourceStart;
+ }
+ expressionStack[expressionPtr] = fieldReference;
+ assistNode = fieldReference;
+ this.lastCheckPoint = fieldReference.sourceEnd + 1;
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+ this.isOrphanCompletionNode = true;
+
+}
+protected void consumeFormalParameter(boolean isVarArgs) {
+ if (this.indexOfAssistIdentifier() < 0) {
+ super.consumeFormalParameter(isVarArgs);
+// if((!diet || dietInt != 0) && astPtr > -1) {
+// Argument argument = (Argument) astStack[astPtr];
+// if(argument.type == assistNode) {
+// isOrphanCompletionNode = true;
+// this.restartRecovery = true; // force to restart in recovery mode
+// this.lastIgnoredToken = -1;
+// }
+// }
+ } else {
+ identifierLengthPtr--;
+ char[] identifierName = identifierStack[identifierPtr];
+ long namePositions = identifierPositionStack[identifierPtr--];
+// int extendedDimensions = this.intStack[this.intPtr--];
+// int endOfEllipsis = 0;
+// if (isVarArgs) {
+// endOfEllipsis = this.intStack[this.intPtr--];
+// }
+// int firstDimensions = this.intStack[this.intPtr--];
+// final int typeDimensions = firstDimensions + extendedDimensions;
+// TypeReference type = getTypeReference(typeDimensions);
+// if (isVarArgs) {
+// type = copyDims(type, typeDimensions + 1);
+// if (extendedDimensions == 0) {
+// type.sourceEnd = endOfEllipsis;
+// }
+// type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+// }
+// int modifierPositions = intStack[intPtr--];
+// intPtr--;
+ int modifierPositions=(int) (namePositions >>> 32);
+ Argument arg =
+ new SelectionOnArgumentName(
+ identifierName,
+ namePositions,
+ null,
+ ClassFileConstants.AccDefault);
+// intStack[intPtr + 1] & ~ClassFileConstants.AccDeprecated); // modifiers
+ arg.declarationSourceStart = modifierPositions;
+ pushOnAstStack(arg);
+
+ assistNode = arg;
+ this.lastCheckPoint = (int) namePositions;
+ isOrphanCompletionNode = true;
+
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+
+ /* if incomplete method header, listLength counter will not have been reset,
+ indicating that some arguments are available on the stack */
+ listLength++;
+ }
+}
+protected void consumeLocalVariableDeclarationStatement() {
+ super.consumeLocalVariableDeclarationStatement();
+
+ // force to restart in recovery mode if the declaration contains the selection
+ if (!this.diet) {
+ LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr];
+ if ((this.selectionStart >= localDeclaration.sourceStart)
+ && (this.selectionEnd <= localDeclaration.sourceEnd)) {
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR;
+ this.lastIgnoredToken = -1;
+ }
+ }
+}
+
+// Nothing here applicable to javascript
+//protected void consumeMethodInvocationPrimary() {
+// //optimize the push/pop
+// //FunctionInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+//
+// char[] selector = identifierStack[identifierPtr];
+// int accessMode;
+// if(selector == this.assistIdentifier()) {
+// if(CharOperation.equals(selector, SUPER)) {
+// accessMode = ExplicitConstructorCall.Super;
+// } else if(CharOperation.equals(selector, THIS)) {
+// accessMode = ExplicitConstructorCall.This;
+// } else {
+// super.consumeMethodInvocationPrimary();
+// return;
+// }
+// } else {
+// super.consumeMethodInvocationPrimary();
+// return;
+// }
+//
+// final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode);
+// constructorCall.sourceEnd = rParenPos;
+// int length;
+// if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+// expressionPtr -= length;
+// System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+// }
+// constructorCall.qualification = expressionStack[expressionPtr--];
+// constructorCall.sourceStart = constructorCall.qualification.sourceStart;
+//
+// if (!diet){
+// pushOnAstStack(constructorCall);
+// this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+// this.lastIgnoredToken = -1;
+// } else {
+// pushOnExpressionStack(new Expression(){
+// public TypeBinding resolveType(BlockScope scope) {
+// constructorCall.resolve(scope);
+// return null;
+// }
+// public StringBuffer printExpression(int indent, StringBuffer output) {
+// return output;
+// }
+// });
+// }
+//
+// this.assistNode = constructorCall;
+// this.lastCheckPoint = constructorCall.sourceEnd + 1;
+// this.isOrphanCompletionNode = true;
+//}
+protected void consumeToken(int token) {
+ super.consumeToken(token);
+
+ // if in a method or if in a field initializer
+ if (isInsideMethod() || isInsideFieldInitialization()) {
+ switch (token) {
+ case TokenNamecase :
+ pushOnElementStack(K_BETWEEN_CASE_AND_COLON);
+ break;
+ case TokenNameCOLON:
+ if(topKnownElementKind(SELECTION_OR_ASSIST_PARSER) == K_BETWEEN_CASE_AND_COLON) {
+ popElement(K_BETWEEN_CASE_AND_COLON);
+ }
+ break;
+ }
+ }
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+ return new SelectionOnImportReference(tokens, positions);
+}
+protected JavadocParser createJavadocParser() {
+ return new SelectionJavadocParser(this);
+}
+protected LocalDeclaration createLocalDeclaration(char[] assistName,int sourceStart,int sourceEnd) {
+ if (this.indexOfAssistIdentifier() < 0) {
+ return super.createLocalDeclaration(assistName, sourceStart, sourceEnd);
+ } else {
+ SelectionOnLocalName local = new SelectionOnLocalName(assistName, sourceStart, sourceEnd);
+ this.assistNode = local;
+ this.lastCheckPoint = sourceEnd + 1;
+ return local;
+ }
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
+ return new SelectionOnQualifiedNameReference(
+ previousIdentifiers,
+ assistName,
+ positions);
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
+ return new SelectionOnQualifiedTypeReference(
+ previousIdentifiers,
+ assistName,
+ positions);
+}
+public NameReference createSingleAssistNameReference(char[] assistName, long position) {
+ return new SelectionOnSingleNameReference(assistName, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
+ return new SelectionOnSingleTypeReference(assistName, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
+
+ this.selectionStart = start;
+ this.selectionEnd = end;
+ SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+ selectionScanner.selectionIdentifier = null;
+ selectionScanner.selectionStart = start;
+ selectionScanner.selectionEnd = end;
+ return this.dietParse(sourceUnit, compilationResult);
+}
+protected NameReference getUnspecifiedReference() {
+ /* build a (unspecified) NameReference which may be qualified*/
+
+ int completionIndex;
+
+ /* no need to take action if not inside completed identifiers */
+ if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+ return super.getUnspecifiedReference();
+ }
+
+ int length = identifierLengthStack[identifierLengthPtr];
+ NameReference nameReference;
+ /* retrieve identifiers subset and whole positions, the completion node positions
+ should include the entire replaced source. */
+ char[][] subset = identifierSubSet(completionIndex);
+ identifierLengthPtr--;
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ /* build specific completion on name reference */
+ if (completionIndex == 0) {
+ /* completion inside first identifier */
+ nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+ } else {
+ /* completion inside subsequent identifier */
+ nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+ }
+ assistNode = nameReference;
+ this.lastCheckPoint = nameReference.sourceEnd + 1;
+ if (!diet){
+ this.restartRecovery = true; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+ this.isOrphanCompletionNode = true;
+ return nameReference;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * In the case of qualified name reference if the cursor location is on the
+ * qualified name reference, then create a CompletionOnQualifiedNameReference
+ * instead.
+ */
+protected NameReference getUnspecifiedReferenceOptimized() {
+
+ int index = indexOfAssistIdentifier();
+ NameReference reference = super.getUnspecifiedReferenceOptimized();
+
+ if (index >= 0){
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+ this.isOrphanCompletionNode = true;
+ }
+ return reference;
+}
+public void initializeScanner(){
+ this.scanner = new SelectionScanner(this.options.sourceLevel);
+}
+protected MessageSend newMessageSend() {
+ // '(' ArgumentListopt ')'
+ // the arguments are on the expression stack
+
+
+
+ int numArgs=expressionLengthStack[expressionLengthPtr];
+ Expression receiver = expressionStack[expressionPtr-numArgs];
+// char[] selector = identifierStack[identifierPtr];
+// if (selector != this.assistIdentifier()){
+
+ if (!(receiver instanceof SelectionOnSingleNameReference || receiver instanceof SelectionOnFieldReference))
+ {
+ return super.newMessageSend();
+ }
+ MessageSend messageSend = new SelectionOnMessageSend();
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ messageSend.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ assistNode = messageSend;
+ if (!diet){
+ this.restartRecovery = AssistParser.STOP_AT_CURSOR; // force to restart in recovery mode
+ this.lastIgnoredToken = -1;
+ }
+
+ this.isOrphanCompletionNode = true;
+ return messageSend;
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
+
+ if (end == -1) return super.parse(sourceUnit, compilationResult, start, end);
+
+ this.selectionStart = start;
+ this.selectionEnd = end;
+ SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+ selectionScanner.selectionIdentifier = null;
+ selectionScanner.selectionStart = start;
+ selectionScanner.selectionEnd = end;
+ return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+ /* if reached assist node inside method body, but still inside nested type,
+ should continue in diet mode until the end of the method body */
+ if (this.assistNode != null
+ && !(referenceContext instanceof CompilationUnitDeclaration)){
+ currentElement.preserveEnclosingBlocks();
+ if (currentElement.enclosingType() == null) {
+ if(!(currentElement instanceof RecoveredType)) {
+ this.resetStacks();
+ return false;
+ }
+
+ RecoveredType recoveredType = (RecoveredType)currentElement;
+ if(recoveredType.typeDeclaration != null && recoveredType.typeDeclaration.allocation == this.assistNode){
+ this.resetStacks();
+ return false;
+ }
+ }
+ }
+ return super.resumeAfterRecovery();
+}
+
+public void selectionIdentifierCheck(){
+ if (checkRecoveredType()) return;
+}
+public void setAssistIdentifier(char[] assistIdent){
+ ((SelectionScanner)scanner).selectionIdentifier = assistIdent;
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+ /* expose parser state to recovery state */
+ currentElement.updateFromParserState();
+
+ /* may be able to retrieve completionNode as an orphan, and then attach it */
+ this.selectionIdentifierCheck();
+ this.attachOrphanCompletionNode();
+
+ // if an assist node has been found and a recovered element exists,
+ // mark enclosing blocks as to be preserved
+ if (this.assistNode != null && this.currentElement != null) {
+ currentElement.preserveEnclosingBlocks();
+ }
+
+ /* check and update recovered state based on current token,
+ this action is also performed when shifting token after recovery
+ got activated once.
+ */
+ this.recoveryTokenCheck();
+}
+
+public String toString() {
+ String s = Util.EMPTY_STRING;
+ s = s + "elementKindStack : int[] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= elementPtr; i++) {
+ s = s + String.valueOf(elementKindStack[i]) + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+ s = s + "elementInfoStack : int[] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= elementPtr; i++) {
+ s = s + String.valueOf(elementInfoStack[i]) + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+ return s + super.toString();
+}
+public int getCursorLocation() {
+ return this.selectionStart;
+}
+
+public void createAssistTypeForAllocation(AllocationExpression expression) {
+
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionScanner.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionScanner.java
new file mode 100644
index 0000000..a11b391
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/codeassist/select/SelectionScanner.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.codeassist.select;
+
+/*
+ * Scanner aware of a selection range. If finding an identifier which source range is exactly
+ * the same, then will record it so that the parser can make use of it.
+ *
+ * Source positions are zero-based and inclusive.
+ */
+import org.eclipse.wst.jsdt.internal.compiler.parser.Scanner;
+
+public class SelectionScanner extends Scanner {
+
+ public char[] selectionIdentifier;
+ public int selectionStart, selectionEnd;
+/*
+ * Truncate the current identifier if it is containing the cursor location. Since completion is performed
+ * on an identifier prefix.
+ *
+ */
+
+public SelectionScanner(long sourceLevel) {
+ super(false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+}
+
+public char[] getCurrentIdentifierSource() {
+
+ if (selectionIdentifier == null){
+ if (selectionStart == startPosition && selectionEnd == currentPosition-1){
+ if (withoutUnicodePtr != 0){ // check unicode scenario
+ System.arraycopy(withoutUnicodeBuffer, 1, selectionIdentifier = new char[withoutUnicodePtr], 0, withoutUnicodePtr);
+ } else {
+ int length = currentPosition - startPosition;
+ // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
+ System.arraycopy(source, startPosition, (selectionIdentifier = new char[length]), 0, length);
+ }
+ return selectionIdentifier;
+ }
+ }
+ return super.getCurrentIdentifierSource();
+}
+/*
+ * In case we actually read a keyword which corresponds to the selected
+ * range, we pretend we read an identifier.
+ */
+public int scanIdentifierOrKeyword() {
+
+ int id = super.scanIdentifierOrKeyword();
+
+ // convert completed keyword into an identifier
+ if (id != TokenNameIdentifier
+ && startPosition == selectionStart
+ && currentPosition == selectionEnd+1){
+ return TokenNameIdentifier;
+ }
+ return id;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ASTVisitor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ASTVisitor.java
new file mode 100644
index 0000000..a4198af
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ASTVisitor.java
@@ -0,0 +1,879 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.infer.InferredAttribute;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BreakStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ClassLiteralAccess;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Clinit;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ContinueStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DebuggerStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DoStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DoubleLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EmptyStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExtendedStringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FalseLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForInStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IfStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.InstanceOfExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArgumentExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArraySingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocImplicitTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LabeledStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ListExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectGetterSetterField;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PostfixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.RegExLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteralConcatenation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TrueLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.WhileStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.WithStatement;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+
+/**
+ * A visitor for iterating through the parse tree.
+ */
+public abstract class ASTVisitor {
+ public void acceptProblem(IProblem problem) {
+ // do nothing by default
+ }
+ public void endVisit(
+ AllocationExpression allocationExpression,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Argument argument, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Argument argument,ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ArrayAllocationExpression arrayAllocationExpression,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ArrayReference arrayReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Assignment assignment, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Block block, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(BreakStatement breakStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(CaseStatement caseStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ClassLiteralAccess classLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Clinit clinit, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ CompilationUnitDeclaration compilationUnitDeclaration,
+ CompilationUnitScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ConditionalExpression conditionalExpression,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ContinueStatement continueStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(DoStatement doStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(EqualExpression equalExpression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ExplicitConstructorCall explicitConstructor,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ ExtendedStringLiteral extendedStringLiteral,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(FalseLiteral falseLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(FieldReference fieldReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(FieldReference fieldReference, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ForeachStatement forStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ForStatement forStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ForInStatement forInStatement, BlockScope scope) {
+ // do nothing by default
+ }
+
+ public void endVisit(FunctionExpression functionExpression, BlockScope scope) {
+ }
+
+ public void endVisit(IfStatement ifStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(InferredType inferredType, BlockScope scope) {
+ // do nothing by default
+ }
+
+ public void endVisit(Initializer initializer, MethodScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ InstanceOfExpression instanceOfExpression,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(IntLiteral intLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Javadoc javadoc, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Javadoc javadoc, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocAllocationExpression expression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocAllocationExpression expression, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArgumentExpression expression, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArrayQualifiedTypeReference typeRef, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArraySingleTypeReference typeRef, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocFieldReference fieldRef, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocImplicitTypeReference implicitTypeReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocImplicitTypeReference implicitTypeReference, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocMessageSend messageSend, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocQualifiedTypeReference typeRef, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocReturnStatement statement, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocSingleNameReference argument, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocSingleTypeReference typeRef, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(LocalDeclaration localDeclaration, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ListExpression listDeclaration, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(MessageSend messageSend, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(MethodDeclaration methodDeclaration, Scope scope) {
+ // do nothing by default
+ }
+ public void endVisit(StringLiteralConcatenation literal, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedAllocationExpression qualifiedAllocationExpression,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedNameReference qualifiedNameReference,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedNameReference qualifiedNameReference,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedThisReference qualifiedThisReference,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedThisReference qualifiedThisReference,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedTypeReference qualifiedTypeReference,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ QualifiedTypeReference qualifiedTypeReference,
+ ClassScope scope) {
+ // do nothing by default
+ }
+
+ public void endVisit(RegExLiteral stringLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+
+
+ public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ SingleNameReference singleNameReference,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ SingleNameReference singleNameReference,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ SingleTypeReference singleTypeReference,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ SingleTypeReference singleTypeReference,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(StringLiteral stringLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(SuperReference superReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(SwitchStatement switchStatement, BlockScope scope) {
+ // do nothing by default
+ }
+
+ public void endVisit(ThisReference thisReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ThisReference thisReference, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(TrueLiteral trueLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(TryStatement tryStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ TypeDeclaration localTypeDeclaration,
+ BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ TypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(UndefinedLiteral undefinedLiteral, BlockScope scope) {
+ // do nothing by default
+ }
+
+ public void endVisit(WhileStatement whileStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(WithStatement whileStatement, BlockScope scope) {
+ // do nothing by default
+ }
+ public boolean visit(
+ AllocationExpression allocationExpression,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Argument argument, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Argument argument, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ArrayAllocationExpression arrayAllocationExpression,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Assignment assignment, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Block block, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(BreakStatement breakStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(CaseStatement caseStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Clinit clinit, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ CompilationUnitDeclaration compilationUnitDeclaration,
+ CompilationUnitScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ConditionalExpression conditionalExpression,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ContinueStatement continueStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(DoStatement doStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ExplicitConstructorCall explicitConstructor,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ ExtendedStringLiteral extendedStringLiteral,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(FieldReference fieldReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(FieldReference fieldReference, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ForeachStatement forStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ForInStatement forInStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ForStatement forStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(FunctionExpression functionExpression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IfStatement ifStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(InferredType inferredType, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(InferredMethod inferredMethod, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(InferredAttribute inferredField, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ InstanceOfExpression instanceOfExpression,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Javadoc javadoc, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Javadoc javadoc, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocAllocationExpression expression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocAllocationExpression expression, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArgumentExpression expression, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArrayQualifiedTypeReference typeRef, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArraySingleTypeReference typeRef, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocFieldReference fieldRef, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocImplicitTypeReference implicitTypeReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocImplicitTypeReference implicitTypeReference, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocMessageSend messageSend, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocQualifiedTypeReference typeRef, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocReturnStatement statement, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocSingleNameReference argument, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocSingleTypeReference typeRef, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ListExpression listDeclaration, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(MessageSend messageSend, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ StringLiteralConcatenation literal,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedAllocationExpression qualifiedAllocationExpression,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedNameReference qualifiedNameReference,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedNameReference qualifiedNameReference,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedThisReference qualifiedThisReference,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedThisReference qualifiedThisReference,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedTypeReference qualifiedTypeReference,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ QualifiedTypeReference qualifiedTypeReference,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(RegExLiteral stringLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ SingleNameReference singleNameReference,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ SingleNameReference singleNameReference,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ SingleTypeReference singleTypeReference,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ SingleTypeReference singleTypeReference,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(SuperReference superReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+
+ public boolean visit(ThisReference thisReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ThisReference thisReference, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(TryStatement tryStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ TypeDeclaration localTypeDeclaration,
+ BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ TypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(UndefinedLiteral undefined, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(WithStatement whileStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ObjectLiteral literal, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public void endVisit(ObjectLiteral literal, BlockScope scope) {
+ }
+ public boolean visit(ObjectLiteralField field, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public void endVisit(ObjectLiteralField field, BlockScope scope) {
+ }
+ public boolean visit(ObjectGetterSetterField field, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public void endVisit(ObjectGetterSetterField field, BlockScope scope) {
+ }
+ public boolean visit(DebuggerStatement statement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public void endVisit(DebuggerStatement statement, BlockScope scope) {
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/CompilationResult.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/CompilationResult.java
new file mode 100644
index 0000000..f6cc296
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/CompilationResult.java
@@ -0,0 +1,464 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+/**
+ * A compilation result consists of all information returned by the compiler for
+ * a single compiled compilation source unit. This includes:
+ *
+ * - the compilation unit that was compiled
+ *
- for each type produced by compiling the compilation unit, its binary and optionally its principal structure
+ *
- any problems (errors or warnings) produced
+ *
- dependency info
+ *
+ *
+ * The principle structure and binary may be null if the compiler could not produce them.
+ * If neither could be produced, there is no corresponding entry for the type.
+ *
+ * The dependency info includes type references such as supertypes, field types, method
+ * parameter and return types, local variable types, types of intermediate expressions, etc.
+ * It also includes the namespaces (packages) in which names were looked up.
+ * It does not include finer grained dependencies such as information about
+ * specific fields and methods which were referenced, but does contain their
+ * declaring types and any other types used to locate such fields or methods.
+ */
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.wst.jsdt.internal.compiler.parser.RecoveryScannerData;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+
+public class CompilationResult {
+
+ public CategorizedProblem problems[];
+ public CategorizedProblem tasks[];
+ public int problemCount;
+ public int taskCount;
+ public ICompilationUnit compilationUnit;
+ private Map problemsMap;
+ private Set firstErrors;
+ private int maxProblemPerUnit;
+ public char[][][] qualifiedReferences;
+ public char[][] simpleNameReferences;
+ public int lineSeparatorPositions[];
+ public RecoveryScannerData recoveryScannerData;
+ public Map compiledTypes = new Hashtable(11);
+ public int unitIndex, totalUnitsKnown;
+ public boolean hasBeenAccepted = false;
+ public char[] fileName;
+ public boolean hasInconsistentToplevelHierarchies = false; // record the fact some toplevel types have inconsistent hierarchies
+ public boolean hasSyntaxError = false;
+ long[] suppressWarningIrritants; // irritant for suppressed warnings
+ long[] suppressWarningScopePositions; // (start << 32) + end
+ int suppressWarningsCount;
+ public char[][] packageName;
+
+private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY;
+private static final Comparator PROBLEM_COMPARATOR = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((CategorizedProblem) o1).getSourceStart() - ((CategorizedProblem) o2).getSourceStart();
+ }
+};
+
+public CompilationResult(
+ char[] fileName,
+ char[][] packageName,
+ int unitIndex,
+ int totalUnitsKnown, int maxProblemPerUnit){
+
+ this.fileName = fileName;
+ this.unitIndex = unitIndex;
+ this.totalUnitsKnown = totalUnitsKnown;
+ this.maxProblemPerUnit = maxProblemPerUnit;
+}
+
+public CompilationResult(
+ ICompilationUnit compilationUnit,
+ int unitIndex,
+ int totalUnitsKnown,
+ int maxProblemPerUnit){
+
+ this.fileName = compilationUnit.getFileName();
+ this.compilationUnit = compilationUnit;
+ this.unitIndex = unitIndex;
+ this.totalUnitsKnown = totalUnitsKnown;
+ this.maxProblemPerUnit = maxProblemPerUnit;
+}
+
+private int computePriority(CategorizedProblem problem){
+ final int P_STATIC = 10000;
+ final int P_OUTSIDE_METHOD = 40000;
+ final int P_FIRST_ERROR = 20000;
+ final int P_ERROR = 100000;
+
+ int priority = 10000 - problem.getSourceLineNumber(); // early problems first
+ if (priority < 0) priority = 0;
+ if (problem.isError()){
+ priority += P_ERROR;
+ }
+ ReferenceContext context = this.problemsMap == null ? null : (ReferenceContext) this.problemsMap.get(problem);
+ if (context != null){
+ if (context instanceof AbstractMethodDeclaration){
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) context;
+ if (method.isStatic()) {
+ priority += P_STATIC;
+ }
+ } else {
+ priority += P_OUTSIDE_METHOD;
+ }
+ if (this.firstErrors.contains(problem)){ // if context is null, firstErrors is null too
+ priority += P_FIRST_ERROR;
+ }
+ } else {
+ priority += P_OUTSIDE_METHOD;
+ }
+ return priority;
+}
+
+public void discardSuppressedWarnings() {
+ if (this.suppressWarningsCount == 0) return;
+ int removed = 0;
+ nextProblem: for (int i = 0, length = this.problemCount; i < length; i++) {
+ CategorizedProblem problem = this.problems[i];
+ int problemID = problem.getID();
+ if (!problem.isWarning()) {
+ continue nextProblem;
+ }
+ int start = problem.getSourceStart();
+ int end = problem.getSourceEnd();
+ nextSuppress: for (int j = 0, max = this.suppressWarningsCount; j < max; j++) {
+ long position = this.suppressWarningScopePositions[j];
+ int startSuppress = (int) (position >>> 32);
+ int endSuppress = (int) position;
+ if (start < startSuppress) continue nextSuppress;
+ if (end > endSuppress) continue nextSuppress;
+ if ((ProblemReporter.getIrritant(problemID) & this.suppressWarningIrritants[j]) == 0)
+ continue nextSuppress;
+ // discard suppressed warning
+ removed++;
+ this.problems[i] = null;
+ if (this.problemsMap != null) this.problemsMap.remove(problem);
+ if (this.firstErrors != null) this.firstErrors.remove(problem);
+ continue nextProblem;
+ }
+ }
+ if (removed > 0) {
+ for (int i = 0, index = 0; i < this.problemCount; i++) {
+ CategorizedProblem problem;
+ if ((problem = this.problems[i]) != null) {
+ if (i > index) {
+ this.problems[index++] = problem;
+ } else {
+ index++;
+ }
+ }
+ }
+ this.problemCount -= removed;
+ }
+}
+
+public CategorizedProblem[] getAllProblems() {
+ CategorizedProblem[] onlyProblems = this.getProblems();
+ int onlyProblemCount = onlyProblems != null ? onlyProblems.length : 0;
+ CategorizedProblem[] onlyTasks = this.getTasks();
+ int onlyTaskCount = onlyTasks != null ? onlyTasks.length : 0;
+ if (onlyTaskCount == 0) {
+ return onlyProblems;
+ }
+ if (onlyProblemCount == 0) {
+ return onlyTasks;
+ }
+
+ int totalNumberOfProblem = onlyProblemCount + onlyTaskCount;
+ CategorizedProblem[] allProblems = new CategorizedProblem[totalNumberOfProblem];
+ int allProblemIndex = 0;
+ int taskIndex = 0;
+ int problemIndex = 0;
+ while (taskIndex + problemIndex < totalNumberOfProblem) {
+ CategorizedProblem nextTask = null;
+ CategorizedProblem nextProblem = null;
+ if (taskIndex < onlyTaskCount) {
+ nextTask = onlyTasks[taskIndex];
+ }
+ if (problemIndex < onlyProblemCount) {
+ nextProblem = onlyProblems[problemIndex];
+ }
+ // select the next problem
+ CategorizedProblem currentProblem = null;
+ if (nextProblem != null) {
+ if (nextTask != null) {
+ if (nextProblem.getSourceStart() < nextTask.getSourceStart()) {
+ currentProblem = nextProblem;
+ problemIndex++;
+ } else {
+ currentProblem = nextTask;
+ taskIndex++;
+ }
+ } else {
+ currentProblem = nextProblem;
+ problemIndex++;
+ }
+ } else {
+ if (nextTask != null) {
+ currentProblem = nextTask;
+ taskIndex++;
+ }
+ }
+ allProblems[allProblemIndex++] = currentProblem;
+ }
+ return allProblems;
+}
+
+
+/**
+ * Answer the initial compilation unit corresponding to the present compilation result
+ */
+public ICompilationUnit getCompilationUnit(){
+ return this.compilationUnit;
+}
+
+/**
+ * Answer the errors encountered during compilation.
+ */
+public CategorizedProblem[] getErrors() {
+ CategorizedProblem[] reportedProblems = getProblems();
+ int errorCount = 0;
+ for (int i = 0; i < this.problemCount; i++) {
+ if (reportedProblems[i].isError()) errorCount++;
+ }
+ if (errorCount == this.problemCount) return reportedProblems;
+ CategorizedProblem[] errors = new CategorizedProblem[errorCount];
+ int index = 0;
+ for (int i = 0; i < this.problemCount; i++) {
+ if (reportedProblems[i].isError()) errors[index++] = reportedProblems[i];
+ }
+ return errors;
+}
+
+
+/**
+ * Answer the initial file name
+ */
+public char[] getFileName(){
+ return this.fileName;
+}
+
+public char [][] getPackageName()
+{
+ if (this.compilationUnit!=null)
+ return this.compilationUnit.getPackageName();
+ return this.packageName;
+}
+
+public int[] getLineSeparatorPositions() {
+ return this.lineSeparatorPositions == null ? CompilationResult.EMPTY_LINE_ENDS : this.lineSeparatorPositions;
+}
+
+/**
+ * Answer the problems (errors and warnings) encountered during compilation.
+ *
+ * This is not a compiler internal API - it has side-effects !
+ * It is intended to be used only once all problems have been detected,
+ * and makes sure the problems slot as the exact size of the number of
+ * problems.
+ */
+public CategorizedProblem[] getProblems() {
+ // Re-adjust the size of the problems if necessary.
+ if (this.problems != null) {
+ discardSuppressedWarnings();
+
+ if (this.problemCount != this.problems.length) {
+ System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount]), 0, this.problemCount);
+ }
+
+ if (this.maxProblemPerUnit > 0 && this.problemCount > this.maxProblemPerUnit){
+ quickPrioritize(this.problems, 0, this.problemCount - 1);
+ this.problemCount = this.maxProblemPerUnit;
+ System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount]), 0, this.problemCount);
+ }
+
+ // Stable sort problems per source positions.
+ Arrays.sort(this.problems, 0, this.problems.length, CompilationResult.PROBLEM_COMPARATOR);
+ //quickSort(problems, 0, problems.length-1);
+ }
+ return this.problems;
+}
+
+/**
+ * Answer the tasks (TO-DO, ...) encountered during compilation.
+ *
+ * This is not a compiler internal API - it has side-effects !
+ * It is intended to be used only once all problems have been detected,
+ * and makes sure the problems slot as the exact size of the number of
+ * problems.
+ */
+public CategorizedProblem[] getTasks() {
+ // Re-adjust the size of the tasks if necessary.
+ if (this.tasks != null) {
+
+ if (this.taskCount != this.tasks.length) {
+ System.arraycopy(this.tasks, 0, (this.tasks = new CategorizedProblem[this.taskCount]), 0, this.taskCount);
+ }
+ // Stable sort problems per source positions.
+ Arrays.sort(this.tasks, 0, this.tasks.length, CompilationResult.PROBLEM_COMPARATOR);
+ //quickSort(tasks, 0, tasks.length-1);
+ }
+ return this.tasks;
+}
+
+public boolean hasErrors() {
+ if (this.problems != null)
+ for (int i = 0; i < this.problemCount; i++) {
+ if (this.problems[i].isError())
+ return true;
+ }
+ return false;
+}
+
+public boolean hasProblems() {
+ return this.problemCount != 0;
+}
+
+public boolean hasTasks() {
+ return this.taskCount != 0;
+}
+
+public boolean hasWarnings() {
+ if (this.problems != null)
+ for (int i = 0; i < this.problemCount; i++) {
+ if (this.problems[i].isWarning())
+ return true;
+ }
+ return false;
+}
+
+private void quickPrioritize(CategorizedProblem[] problemList, int left, int right) {
+ if (left >= right) return;
+
+ // sort the problems by their priority... starting with the highest priority
+ int original_left = left;
+ int original_right = right;
+ int mid = computePriority(problemList[left + (right - left) / 2]);
+ do {
+ while (computePriority(problemList[right]) < mid)
+ right--;
+ while (mid < computePriority(problemList[left]))
+ left++;
+ if (left <= right) {
+ CategorizedProblem tmp = problemList[left];
+ problemList[left] = problemList[right];
+ problemList[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right)
+ quickPrioritize(problemList, original_left, right);
+ if (left < original_right)
+ quickPrioritize(problemList, left, original_right);
+}
+/*
+ * Record the compilation unit result's package name
+ */
+public void recordPackageName(char[][] packName) {
+ this.packageName = packName;
+}
+public void record(CategorizedProblem newProblem, ReferenceContext referenceContext) {
+ //new Exception("VERBOSE PROBLEM REPORTING").printStackTrace();
+ if(newProblem.getID() == IProblem.Task) {
+ recordTask(newProblem);
+ return;
+ }
+ if (this.problemCount == 0) {
+ this.problems = new CategorizedProblem[5];
+ } else if (this.problemCount == this.problems.length) {
+ System.arraycopy(this.problems, 0, (this.problems = new CategorizedProblem[this.problemCount * 2]), 0, this.problemCount);
+ }
+ this.problems[this.problemCount++] = newProblem;
+ if (referenceContext != null){
+ if (this.problemsMap == null) this.problemsMap = new HashMap(5);
+ if (this.firstErrors == null) this.firstErrors = new HashSet(5);
+ if (newProblem.isError() && !referenceContext.hasErrors()) this.firstErrors.add(newProblem);
+ this.problemsMap.put(newProblem, referenceContext);
+ }
+ if ((newProblem.getID() & IProblem.Syntax) != 0 && newProblem.isError())
+ this.hasSyntaxError = true;
+}
+
+
+
+public void recordSuppressWarnings(long irritant, int scopeStart, int scopeEnd) {
+ if (this.suppressWarningIrritants == null) {
+ this.suppressWarningIrritants = new long[3];
+ this.suppressWarningScopePositions = new long[3];
+ } else if (this.suppressWarningIrritants.length == this.suppressWarningsCount) {
+ System.arraycopy(this.suppressWarningIrritants, 0,this.suppressWarningIrritants = new long[2*this.suppressWarningsCount], 0, this.suppressWarningsCount);
+ System.arraycopy(this.suppressWarningScopePositions, 0,this.suppressWarningScopePositions = new long[2*this.suppressWarningsCount], 0, this.suppressWarningsCount);
+ }
+ this.suppressWarningIrritants[this.suppressWarningsCount] = irritant;
+ this.suppressWarningScopePositions[this.suppressWarningsCount++] = ((long)scopeStart<<32) + scopeEnd;
+}
+
+private void recordTask(CategorizedProblem newProblem) {
+ if (this.taskCount == 0) {
+ this.tasks = new CategorizedProblem[5];
+ } else if (this.taskCount == this.tasks.length) {
+ System.arraycopy(this.tasks, 0, (this.tasks = new CategorizedProblem[this.taskCount * 2]), 0, this.taskCount);
+ }
+ this.tasks[this.taskCount++] = newProblem;
+}
+
+public CompilationResult tagAsAccepted(){
+ this.hasBeenAccepted = true;
+ this.problemsMap = null; // flush
+ this.firstErrors = null; // flush
+ return this;
+}
+
+public String toString(){
+ StringBuffer buffer = new StringBuffer();
+ if (this.fileName != null){
+ buffer.append("Filename : ").append(this.fileName).append('\n'); //$NON-NLS-1$
+ }
+ if (this.compiledTypes != null){
+ buffer.append("COMPILED type(s) \n"); //$NON-NLS-1$
+ Iterator keys = this.compiledTypes.keySet().iterator();
+ while (keys.hasNext()) {
+ char[] typeName = (char[]) keys.next();
+ buffer.append("\t - ").append(typeName).append('\n'); //$NON-NLS-1$
+
+ }
+ } else {
+ buffer.append("No COMPILED type\n"); //$NON-NLS-1$
+ }
+ if (this.problems != null){
+ buffer.append(this.problemCount).append(" PROBLEM(s) detected \n"); //$NON-NLS-1$
+ for (int i = 0; i < this.problemCount; i++){
+ buffer.append("\t - ").append(this.problems[i]).append('\n'); //$NON-NLS-1$
+ }
+ } else {
+ buffer.append("No PROBLEM\n"); //$NON-NLS-1$
+ }
+ return buffer.toString();
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/Compiler.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/Compiler.java
new file mode 100644
index 0000000..0b81613
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/Compiler.java
@@ -0,0 +1,713 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Michael Spector - Bug 243886
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.env.IBinaryType;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ITypeRequestor;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblem;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.wst.jsdt.internal.compiler.util.Messages;
+import org.eclipse.wst.jsdt.internal.compiler.util.SimpleSetOfCharArray;
+import org.eclipse.wst.jsdt.internal.core.builder.SourceFile;
+import org.eclipse.wst.jsdt.internal.oaametadata.LibraryAPIs;
+
+public class Compiler implements ITypeRequestor, ProblemSeverities {
+ public Parser parser;
+ public ICompilerRequestor requestor;
+ public CompilerOptions options;
+ public ProblemReporter problemReporter;
+ protected PrintWriter out; // output for messages that are not sent to problemReporter
+
+ // management of unit to be processed
+ public CompilationUnitDeclaration[] unitsToProcess;
+ public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
+
+ // name lookup
+ public LookupEnvironment lookupEnvironment;
+
+ // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
+ public static boolean DEBUG = false;
+ public int parseThreshold = -1;
+
+ public ReferenceBinding[] referenceBindings;
+ protected HashtableOfObject parsedUnits;
+
+
+ // number of initial units parsed at once (-1: none)
+
+ /*
+ * Static requestor reserved to listening compilation results in debug mode,
+ * so as for example to monitor compiler activity independantly from a particular
+ * builder implementation. It is reset at the end of compilation, and should not
+ * persist any information after having been reset.
+ */
+ public static IDebugRequestor DebugRequestor = null;
+
+ /**
+ * Answer a new compiler using the given name environment and compiler options.
+ * The environment and options will be in effect for the lifetime of the compiler.
+ * When the compiler is run, compilation results are sent to the given requestor.
+ *
+ * @param environment org.eclipse.wst.jsdt.internal.compiler.api.env.INameEnvironment
+ * Environment used by the compiler in order to resolve type and package
+ * names. The name environment implements the actual connection of the compiler
+ * to the outside world (e.g. in batch mode the name environment is performing
+ * pure file accesses, reuse previous build state or connection to repositories).
+ * Note: the name environment is responsible for implementing the actual classpath
+ * rules.
+ *
+ * @param policy org.eclipse.wst.jsdt.internal.compiler.api.problem.IErrorHandlingPolicy
+ * Configurable part for problem handling, allowing the compiler client to
+ * specify the rules for handling problems (stop on first error or accumulate
+ * them all) and at the same time perform some actions such as opening a dialog
+ * in UI when compiling interactively.
+ * @see org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies
+ *
+ * @param options org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions
+ * The options that control the compiler behavior.
+ *
+ * @param requestor org.eclipse.wst.jsdt.internal.compiler.api.ICompilerRequestor
+ * Component which will receive and persist all compilation results and is intended
+ * to consume them as they are produced. Typically, in a batch compiler, it is
+ * responsible for writing out the actual .class files to the file system.
+ * @see org.eclipse.wst.jsdt.internal.compiler.CompilationResult
+ *
+ * @param problemFactory org.eclipse.wst.jsdt.internal.compiler.api.problem.IProblemFactory
+ * Factory used inside the compiler to create problem descriptors. It allows the
+ * compiler client to supply its own representation of compilation problems in
+ * order to avoid object conversions. Note that the factory is not supposed
+ * to accumulate the created problems, the compiler will gather them all and hand
+ * them back as part of the compilation unit result.
+ */
+ public Compiler(
+ INameEnvironment environment,
+ IErrorHandlingPolicy policy,
+ CompilerOptions options,
+ final ICompilerRequestor requestor,
+ IProblemFactory problemFactory) {
+ this(environment, policy, options, requestor, problemFactory, null);
+ }
+
+ /**
+ * Answer a new compiler using the given name environment and compiler options.
+ * The environment and options will be in effect for the lifetime of the compiler.
+ * When the compiler is run, compilation results are sent to the given requestor.
+ *
+ * @param environment org.eclipse.wst.jsdt.internal.compiler.api.env.INameEnvironment
+ * Environment used by the compiler in order to resolve type and package
+ * names. The name environment implements the actual connection of the compiler
+ * to the outside world (e.g. in batch mode the name environment is performing
+ * pure file accesses, reuse previous build state or connection to repositories).
+ * Note: the name environment is responsible for implementing the actual classpath
+ * rules.
+ *
+ * @param policy org.eclipse.wst.jsdt.internal.compiler.api.problem.IErrorHandlingPolicy
+ * Configurable part for problem handling, allowing the compiler client to
+ * specify the rules for handling problems (stop on first error or accumulate
+ * them all) and at the same time perform some actions such as opening a dialog
+ * in UI when compiling interactively.
+ * @see org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies
+ *
+ * @param options org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions
+ * The options that control the compiler behavior.
+ *
+ * @param requestor org.eclipse.wst.jsdt.internal.compiler.api.ICompilerRequestor
+ * Component which will receive and persist all compilation results and is intended
+ * to consume them as they are produced. Typically, in a batch compiler, it is
+ * responsible for writing out the actual .class files to the file system.
+ * @see org.eclipse.wst.jsdt.internal.compiler.CompilationResult
+ *
+ * @param problemFactory org.eclipse.wst.jsdt.internal.compiler.api.problem.IProblemFactory
+ * Factory used inside the compiler to create problem descriptors. It allows the
+ * compiler client to supply its own representation of compilation problems in
+ * order to avoid object conversions. Note that the factory is not supposed
+ * to accumulate the created problems, the compiler will gather them all and hand
+ * them back as part of the compilation unit result.
+ */
+ public Compiler(
+ INameEnvironment environment,
+ IErrorHandlingPolicy policy,
+ CompilerOptions options,
+ final ICompilerRequestor requestor,
+ IProblemFactory problemFactory,
+ PrintWriter out) {
+
+ this.options = options;
+
+ // wrap requestor in DebugRequestor if one is specified
+ if(DebugRequestor == null) {
+ this.requestor = requestor;
+ } else {
+ this.requestor = new ICompilerRequestor(){
+ public void acceptResult(CompilationResult result){
+ if (DebugRequestor.isActive()){
+ DebugRequestor.acceptDebugResult(result);
+ }
+ requestor.acceptResult(result);
+ }
+ };
+ }
+ this.problemReporter = new ProblemReporter(policy, this.options, problemFactory);
+ this.lookupEnvironment = new LookupEnvironment(this, this.options, problemReporter, environment);
+ this.out = out == null ? new PrintWriter(System.out, true) : out;
+ initializeParser();
+ }
+
+ /**
+ * Add an additional binary type
+ */
+ public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+// if (this.options.verbose) {
+// this.out.println(
+// Messages.bind(Messages.compilation_loadBinary, new String(binaryType.getName())));
+//// new Exception("TRACE BINARY").printStackTrace(System.out);
+//// System.out.println();
+// }
+// lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
+ }
+
+ /**
+ * Add an additional compilation unit into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+ public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
+ // Switch the current policy and compilation result for this unit to the requested one.
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
+ unitResult.packageName=sourceUnit.getPackageName();
+ try {
+ if (options.verbose) {
+ String count = String.valueOf(totalUnits + 1);
+ this.out.println(
+ Messages.bind(Messages.compilation_request,
+ new String[] {
+ count,
+ count,
+ new String(sourceUnit.getFileName())
+ }));
+ }
+ if (parsedUnits == null)
+ parsedUnits = new HashtableOfObject();
+ CompilationUnitDeclaration parsedUnit = (CompilationUnitDeclaration) parsedUnits.get(sourceUnit.getFileName());
+ if (parsedUnit == null) {
+ // diet parsing for large collection of unit
+ if (totalUnits < parseThreshold) {
+ parsedUnit = parser.parse(sourceUnit, unitResult);
+ }
+ else {
+ parsedUnit = parser.dietParse(sourceUnit, unitResult);
+ }
+ parsedUnit.bits |= ASTNode.IsImplicitUnit;
+ parser.inferTypes(parsedUnit, this.options);
+ parsedUnits.put(sourceUnit.getFileName(), parsedUnit);
+ if (sourceUnit instanceof SourceFile)
+ this.addCompilationUnit(sourceUnit, parsedUnit);
+ }
+ // initial type binding creation
+ lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
+
+ // binding resolution
+ lookupEnvironment.completeTypeBindings(parsedUnit);
+ } catch (AbortCompilationUnit e) {
+ // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+ // one requested further along to resolve sourceUnit.
+ if (unitResult.compilationUnit == sourceUnit) { // only report once
+ requestor.acceptResult(unitResult.tagAsAccepted());
+ } else {
+ throw e; // want to abort enclosing request to compile
+ }
+ }
+ }
+
+ public void accept(LibraryAPIs libraryMetaData)
+ {
+ lookupEnvironment.buildTypeBindings(libraryMetaData);
+
+ }
+
+
+ public CompilationUnitDeclaration doParse(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
+ try {
+ if (options.verbose) {
+ String count = String.valueOf(totalUnits + 1);
+ this.out.println(
+ Messages.bind(Messages.compilation_request,
+ new String[] {
+ count,
+ count,
+ new String(sourceUnit.getFileName())
+ }));
+ }
+ // diet parsing for large collection of unit
+ CompilationUnitDeclaration parsedUnit;
+ if (totalUnits < parseThreshold) {
+ parsedUnit = parser.parse(sourceUnit, unitResult);
+ } else {
+ parsedUnit = parser.dietParse(sourceUnit, unitResult);
+ }
+ parser.inferTypes(parsedUnit,this.options);
+ return parsedUnit;
+ } catch (AbortCompilationUnit e) {
+// // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+// // one requested further along to resolve sourceUnit.
+// if (unitResult.compilationUnit == sourceUnit) { // only report once
+// requestor.acceptResult(unitResult.tagAsAccepted());
+// } else {
+ throw e; // want to abort enclosing request to compile
+// }
+ }
+ }
+
+
+ /**
+ * Add additional source types
+ */
+ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ problemReporter.abortDueToInternalError(
+ Messages.bind(Messages.abort_againstSourceModel, new String[] { String.valueOf(sourceTypes[0].getName()), String.valueOf(sourceTypes[0].getFileName()) }));
+ }
+
+ protected void addCompilationUnit(
+ ICompilationUnit sourceUnit,
+ CompilationUnitDeclaration parsedUnit) {
+
+ // append the unit to the list of ones to process later on
+ int size = unitsToProcess.length;
+ if (totalUnits == size)
+ // when growing reposition units starting at position 0
+ System.arraycopy(
+ unitsToProcess,
+ 0,
+ (unitsToProcess = new CompilationUnitDeclaration[size * 2]),
+ 0,
+ totalUnits);
+ unitsToProcess[totalUnits++] = parsedUnit;
+ }
+
+ /**
+ * Add the initial set of compilation units into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+ protected void beginToCompile(ICompilationUnit[] sourceUnits) {
+ int maxUnits = sourceUnits.length;
+ this.totalUnits = 0;
+ this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+
+ internalBeginToCompile(sourceUnits, maxUnits);
+ }
+
+ /**
+ * General API
+ * -> compile each of supplied files
+ * -> recompile any required types for which we have an incomplete principle structure
+ */
+ public void compile(ICompilationUnit[] sourceUnits) {
+ CompilationUnitDeclaration unit = null;
+ int i = 0;
+ try {
+ // build and record parsed units
+
+ beginToCompile(sourceUnits);
+
+ // process all units (some more could be injected in the loop by the lookup environment)
+ for (; i < this.totalUnits; i++) {
+ unit = unitsToProcess[i];
+ try {
+ if (options.verbose)
+ this.out.println(
+ Messages.bind(Messages.compilation_process,
+ new String[] {
+ String.valueOf(i + 1),
+ String.valueOf(this.totalUnits),
+ new String(unitsToProcess[i].getFileName())
+ }));
+ process(unit, i);
+ } finally {
+ // cleanup compilation unit result
+ unit.cleanUp();
+ }
+ unitsToProcess[i] = null; // release reference to processed unit declaration
+ requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ if (options.verbose)
+ this.out.println(
+ Messages.bind(Messages.compilation_done,
+ new String[] {
+ String.valueOf(i + 1),
+ String.valueOf(this.totalUnits),
+ new String(unit.getFileName())
+ }));
+ }
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+ this.reset();
+ }
+ if (options.verbose) {
+ if (this.totalUnits > 1) {
+ this.out.println(
+ Messages.bind(Messages.compilation_units, String.valueOf(this.totalUnits)));
+ } else {
+ this.out.println(
+ Messages.bind(Messages.compilation_unit, String.valueOf(this.totalUnits)));
+ }
+ }
+ }
+ /*
+ * Compiler crash recovery in case of unexpected runtime exceptions
+ */
+ protected void handleInternalException(
+ Throwable internalException,
+ CompilationUnitDeclaration unit,
+ CompilationResult result) {
+
+ if (!this.options.enableSemanticValidation)
+ return;
+
+ if ((result == null) && (unit != null)) {
+ result = unit.compilationResult; // current unit being processed ?
+ }
+ // Lookup environment may be in middle of connecting types
+ if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
+ result = lookupEnvironment.unitBeingCompleted.compilationResult;
+ }
+ // Lookup environment may be in middle of connecting types
+ if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
+ result = lookupEnvironment.unitBeingCompleted.compilationResult;
+ }
+ if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+ result = unitsToProcess[totalUnits - 1].compilationResult;
+ // last unit in beginToCompile ?
+
+ boolean needToPrint = true;
+ if (result != null) {
+ /* create and record a compilation problem */
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = new PrintWriter(stringWriter);
+ internalException.printStackTrace(writer);
+ StringBuffer buffer = stringWriter.getBuffer();
+
+ String[] pbArguments = new String[] {
+ Messages.compilation_internalError
+ + "\n" //$NON-NLS-1$
+ + buffer.toString()};
+
+ result
+ .record(
+ problemReporter
+ .createProblem(
+ result.getFileName(),
+ IProblem.Unclassified,
+ pbArguments,
+ pbArguments,
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0, // line number
+ 0),// column number
+ unit);
+
+ /* hand back the compilation result */
+ if (!result.hasBeenAccepted) {
+ requestor.acceptResult(result.tagAsAccepted());
+ needToPrint = false;
+ }
+ }
+ if (needToPrint) {
+ /* dump a stack trace to the console */
+ internalException.printStackTrace();
+ }
+ }
+
+ public void setBinaryTypes(ReferenceBinding[] binaryTypes) {
+ this.referenceBindings = binaryTypes;
+ }
+ /*
+ * Compiler recovery in case of internal AbortCompilation event
+ */
+ protected void handleInternalException(
+ AbortCompilation abortException,
+ CompilationUnitDeclaration unit) {
+
+ if (!this.options.enableSemanticValidation)
+ return;
+
+ /* special treatment for SilentAbort: silently cancelling the compilation process */
+ if (abortException.isSilent) {
+ if (abortException.silentException == null) {
+ return;
+ }
+ throw abortException.silentException;
+ }
+
+ /* uncomment following line to see where the abort came from */
+ // abortException.printStackTrace();
+
+ // Exception may tell which compilation result it is related, and which problem caused it
+ CompilationResult result = abortException.compilationResult;
+ if ((result == null) && (unit != null)) {
+ result = unit.compilationResult; // current unit being processed ?
+ }
+ // Lookup environment may be in middle of connecting types
+ if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
+ result = lookupEnvironment.unitBeingCompleted.compilationResult;
+ }
+ if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+ result = unitsToProcess[totalUnits - 1].compilationResult;
+ // last unit in beginToCompile ?
+ if (result != null && !result.hasBeenAccepted) {
+ /* distant problem which could not be reported back there? */
+ if (abortException.problem != null) {
+ recordDistantProblem: {
+ CategorizedProblem distantProblem = abortException.problem;
+ CategorizedProblem[] knownProblems = result.problems;
+ for (int i = 0; i < result.problemCount; i++) {
+ if (knownProblems[i] == distantProblem) { // already recorded
+ break recordDistantProblem;
+ }
+ }
+ if (distantProblem instanceof DefaultProblem) { // fixup filename TODO (philippe) should improve API to make this official
+ ((DefaultProblem) distantProblem).setOriginatingFileName(result.getFileName());
+ }
+ result.record(distantProblem, unit);
+ }
+ } else {
+ /* distant internal exception which could not be reported back there */
+ if (abortException.exception != null) {
+ this.handleInternalException(abortException.exception, null, result);
+ return;
+ }
+ }
+ /* hand back the compilation result */
+ if (!result.hasBeenAccepted) {
+ requestor.acceptResult(result.tagAsAccepted());
+ }
+ } else {
+ abortException.printStackTrace();
+ }
+ }
+
+ public void initializeParser() {
+
+ this.parser = new Parser(this.problemReporter, this.options.parseLiteralExpressionsAsConstants);
+ this.parser.javadocParser=new SourceJavadocParser(this.parser);
+ this.parser.javadocParser.checkDocComment=true;
+ }
+
+ /**
+ * Add the initial set of compilation units into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+ protected void internalBeginToCompile(ICompilationUnit[] sourceUnits, int maxUnits) {
+ SimpleSetOfCharArray allDefinedTypes = new SimpleSetOfCharArray();
+ // Switch the current policy and compilation result for this unit to the requested one.
+ for (int i = 0; i < maxUnits; i++) {
+ CompilationUnitDeclaration parsedUnit;
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit);
+ try {
+ if (options.verbose) {
+ this.out.println(
+ Messages.bind(Messages.compilation_request,
+ new String[] {
+ String.valueOf(i + 1),
+ String.valueOf(maxUnits),
+ new String(sourceUnits[i].getFileName())
+ }));
+ }
+ // diet parsing for large collection of units
+ if (totalUnits < parseThreshold) {
+ parsedUnit = parser.parse(sourceUnits[i], unitResult);
+ } else {
+ parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
+ }
+ parser.inferTypes(parsedUnit,this.options);
+
+ SimpleSetOfCharArray defined = new SimpleSetOfCharArray();
+ for (int j = 0; j < parsedUnit.numberInferredTypes; j++) {
+ if (parsedUnit.inferredTypes[j].isDefinition && !parsedUnit.inferredTypes[j].isEmptyGlobal()) {
+ defined.add(parsedUnit.inferredTypes[j].getName());
+ allDefinedTypes.add(parsedUnit.inferredTypes[j].getName());
+ }
+ }
+ // initial type binding creation
+ this.addCompilationUnit(sourceUnits[i], parsedUnit);
+ lookupEnvironment.buildTypeBindings(parsedUnit, defined.values, null /*no access restriction*/);
+ ImportReference currentPackage = parsedUnit.currentPackage;
+ if (currentPackage != null) {
+ unitResult.recordPackageName(currentPackage.tokens);
+ }
+ //} catch (AbortCompilationUnit e) {
+ // requestor.acceptResult(unitResult.tagAsAccepted());
+ } finally {
+ sourceUnits[i] = null; // no longer hold onto the unit
+ }
+ }
+ // binding resolution
+ lookupEnvironment.completeTypeBindings(allDefinedTypes.values);
+ }
+
+ /**
+ * Process a compilation unit already parsed and build.
+ */
+ public void process(CompilationUnitDeclaration unit, int i) {
+ this.lookupEnvironment.unitBeingCompleted = unit;
+
+ this.parser.getMethodBodies(unit);
+
+ // fault in fields & methods
+ if (unit.scope != null)
+ unit.scope.faultInTypes();
+
+ // verify inherited methods
+ if (unit.scope != null)
+ unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+
+ // type checking
+ unit.resolve();
+
+ unit.analyseCode();
+
+
+ // reference info
+ if (options.produceReferenceInfo && unit.scope != null)
+ unit.scope.storeDependencyInfo();
+
+ // refresh the total number of units known at this stage
+ unit.compilationResult.totalUnitsKnown = totalUnits;
+
+ this.lookupEnvironment.unitBeingCompleted = null;
+ }
+
+ public void reset() {
+ lookupEnvironment.reset();
+ parser.scanner.source = null;
+ unitsToProcess = null;
+ if(parsedUnits != null)
+ parsedUnits.clear();
+ if (DebugRequestor != null) DebugRequestor.reset();
+ this.problemReporter.reset();
+ }
+
+ /**
+ * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+ */
+ public CompilationUnitDeclaration resolve(
+ CompilationUnitDeclaration unit,
+ ICompilationUnit sourceUnit,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ try {
+ if (unit == null) {
+ // build and record parsed units
+ parseThreshold = 0; // will request a full parse
+ beginToCompile(new ICompilationUnit[] { sourceUnit });
+ // process all units (some more could be injected in the loop by the lookup environment)
+ unit = unitsToProcess[0];
+ } else {
+ // initial type binding creation
+ lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
+
+ // binding resolution
+ lookupEnvironment.completeTypeBindings();
+ }
+ this.lookupEnvironment.unitBeingCompleted = unit;
+ this.parser.getMethodBodies(unit);
+ if (unit.scope != null) {
+ // fault in fields & methods
+ unit.scope.faultInTypes();
+ if (unit.scope != null && verifyMethods) {
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+ // verify inherited methods
+ unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+ }
+ // type checking
+ unit.resolve();
+
+ // flow analysis
+ if (analyzeCode) unit.analyseCode();
+
+ // code generation
+// if (generateCode) unit.generateCode();
+ }
+ if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
+ requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ return unit;
+ } catch (AbortCompilation e) {
+ this.handleInternalException(e, unit);
+ return unit == null ? unitsToProcess[0] : unit;
+ } catch (Error e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } catch (RuntimeException e) {
+ this.handleInternalException(e, unit, null);
+ throw e; // rethrow
+ } finally {
+// this.lookupEnvironment.unitBeingCompleted = null;
+ // leave this.lookupEnvironment.unitBeingCompleted set to the unit, until another unit is resolved
+ // other calls to dom can cause classpath errors to be detected, resulting in AbortCompilation exceptions // No reset is performed there anymore since,
+
+ // within the CodeAssist (or related tools),
+ // the compiler may be called *after* a call
+ // to this resolve(...) method. And such a call
+ // needs to have a compiler with a non-empty
+ // environment.
+ // this.reset();
+ }
+ }
+ /**
+ * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+ */
+ public CompilationUnitDeclaration resolve(
+ ICompilationUnit sourceUnit,
+ boolean verifyMethods,
+ boolean analyzeCode,
+ boolean generateCode) {
+
+ return resolve(
+ null,
+ sourceUnit,
+ verifyMethods,
+ analyzeCode,
+ generateCode);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/DefaultErrorHandlingPolicies.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/DefaultErrorHandlingPolicies.java
new file mode 100644
index 0000000..cf6eb82
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/DefaultErrorHandlingPolicies.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+public class DefaultErrorHandlingPolicies {
+
+/*
+ * Accumulate all problems, then exit without proceeding.
+ *
+ * Typically, the #proceedWithProblems(Problem[]) should
+ * show the problems.
+ *
+ */
+public static IErrorHandlingPolicy exitAfterAllProblems() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors(){
+ return false;
+ }
+ };
+}
+/*
+ * Exit without proceeding on the first problem wich appears
+ * to be an error.
+ *
+ */
+public static IErrorHandlingPolicy exitOnFirstError() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return true;
+ }
+ public boolean proceedOnErrors(){
+ return false;
+ }
+ };
+}
+/*
+ * Proceed on the first error met.
+ *
+ */
+public static IErrorHandlingPolicy proceedOnFirstError() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return true;
+ }
+ public boolean proceedOnErrors(){
+ return true;
+ }
+ };
+}
+/*
+ * Accumulate all problems, then proceed with them.
+ *
+ */
+public static IErrorHandlingPolicy proceedWithAllProblems() {
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors(){
+ return true;
+ }
+ };
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/DelegateASTVisitor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/DelegateASTVisitor.java
new file mode 100644
index 0000000..828bc8c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/DelegateASTVisitor.java
@@ -0,0 +1,866 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import org.eclipse.wst.jsdt.core.compiler.IProblem;
+import org.eclipse.wst.jsdt.core.infer.InferredAttribute;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Block;
+import org.eclipse.wst.jsdt.internal.compiler.ast.BreakStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompoundAssignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ContinueStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DoStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.DoubleLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EmptyStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExtendedStringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FalseLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForInStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IfStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.InstanceOfExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Javadoc;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArgumentExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocArraySingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocImplicitTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LabeledStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ListExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.OR_OR_Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteralField;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PostfixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.PrefixExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.RegExLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.StringLiteralConcatenation;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SuperReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThrowStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TrueLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TryStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.UndefinedLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.WhileStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ast.WithStatement;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+
+
+/**
+ * A visitor for iterating through the parse tree.
+ */
+public class DelegateASTVisitor extends ASTVisitor {
+ org.eclipse.wst.jsdt.core.ast.ASTVisitor visitor;
+ public DelegateASTVisitor(org.eclipse.wst.jsdt.core.ast.ASTVisitor visitor)
+ {
+ this.visitor=visitor;
+ }
+
+
+ public void acceptProblem(IProblem problem) {
+ visitor.acceptProblem(problem);
+ }
+ public void endVisit(
+ AllocationExpression allocationExpression,
+ BlockScope scope) {
+ visitor.endVisit(allocationExpression);
+ }
+ public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+ visitor.endVisit(and_and_Expression);
+ }
+ public void endVisit(Argument argument, BlockScope scope) {
+ visitor.endVisit(argument);
+ }
+ public void endVisit(Argument argument,ClassScope scope) {
+ visitor.endVisit(argument);
+ }
+ public void endVisit(
+ ArrayAllocationExpression arrayAllocationExpression,
+ BlockScope scope) {
+ visitor.endVisit(arrayAllocationExpression);
+ }
+ public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
+ visitor.endVisit(arrayInitializer);
+ }
+ public void endVisit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ BlockScope scope) {
+ visitor.endVisit(arrayQualifiedTypeReference);
+ }
+ public void endVisit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ ClassScope scope) {
+ visitor.endVisit(arrayQualifiedTypeReference);
+ }
+ public void endVisit(ArrayReference arrayReference, BlockScope scope) {
+ visitor.endVisit(arrayReference);
+ }
+ public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ visitor.endVisit(arrayTypeReference);
+ }
+ public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ visitor.endVisit(arrayTypeReference);
+ }
+ public void endVisit(Assignment assignment, BlockScope scope) {
+ visitor.endVisit(assignment);
+ }
+ public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
+ visitor.endVisit(binaryExpression);
+ }
+ public void endVisit(Block block, BlockScope scope) {
+ visitor.endVisit(block);
+ }
+ public void endVisit(BreakStatement breakStatement, BlockScope scope) {
+ visitor.endVisit(breakStatement);
+ }
+ public void endVisit(CaseStatement caseStatement, BlockScope scope) {
+ visitor.endVisit(caseStatement);
+ }
+
+ public void endVisit(
+ CompilationUnitDeclaration compilationUnitDeclaration,
+ CompilationUnitScope scope) {
+ visitor.endVisit(compilationUnitDeclaration);
+ }
+ public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
+ visitor.endVisit(compoundAssignment);
+ }
+ public void endVisit(
+ ConditionalExpression conditionalExpression,
+ BlockScope scope) {
+ visitor.endVisit(conditionalExpression);
+ }
+ public void endVisit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+ visitor.endVisit(constructorDeclaration);
+ }
+ public void endVisit(ContinueStatement continueStatement, BlockScope scope) {
+ visitor.endVisit(continueStatement);
+ }
+ public void endVisit(DoStatement doStatement, BlockScope scope) {
+ visitor.endVisit(doStatement);
+ }
+ public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
+ visitor.endVisit(doubleLiteral);
+ }
+ public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+ visitor.endVisit(emptyStatement);
+ }
+ public void endVisit(EqualExpression equalExpression, BlockScope scope) {
+ visitor.endVisit(equalExpression);
+ }
+ public void endVisit(
+ ExplicitConstructorCall explicitConstructor,
+ BlockScope scope) {
+ visitor.endVisit(explicitConstructor);
+ }
+ public void endVisit(
+ ExtendedStringLiteral extendedStringLiteral,
+ BlockScope scope) {
+ visitor.endVisit(extendedStringLiteral);
+ }
+ public void endVisit(FalseLiteral falseLiteral, BlockScope scope) {
+ visitor.endVisit(falseLiteral);
+ }
+ public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ visitor.endVisit( fieldDeclaration);
+ }
+ public void endVisit(FieldReference fieldReference, BlockScope scope) {
+ visitor.endVisit( fieldReference);
+ }
+ public void endVisit(FieldReference fieldReference, ClassScope scope) {
+ visitor.endVisit(fieldReference);
+ }
+ public void endVisit(ForeachStatement forStatement, BlockScope scope) {
+ visitor.endVisit(forStatement);
+ }
+ public void endVisit(ForStatement forStatement, BlockScope scope) {
+ visitor.endVisit(forStatement);
+ }
+ public void endVisit(ForInStatement forInStatement, BlockScope scope) {
+ visitor.endVisit(forInStatement);
+ }
+
+ public void endVisit(FunctionExpression functionExpression, BlockScope scope) {
+ visitor.endVisit(functionExpression);
+ }
+
+ public void endVisit(IfStatement ifStatement, BlockScope scope) {
+ visitor.endVisit(ifStatement);
+ }
+ public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
+ visitor.endVisit(importRef);
+ }
+ public void endVisit(InferredType inferredType, BlockScope scope) {
+ visitor.endVisit(inferredType);
+ }
+
+ public void endVisit(Initializer initializer, MethodScope scope) {
+ visitor.endVisit(initializer);
+ }
+ public void endVisit(
+ InstanceOfExpression instanceOfExpression,
+ BlockScope scope) {
+ visitor.endVisit(instanceOfExpression);
+ }
+ public void endVisit(IntLiteral intLiteral, BlockScope scope) {
+ visitor.endVisit(intLiteral);
+ }
+ public void endVisit(Javadoc javadoc, BlockScope scope) {
+ visitor.endVisit(javadoc);
+ }
+ public void endVisit(Javadoc javadoc, ClassScope scope) {
+ visitor.endVisit(javadoc);
+ }
+ public void endVisit(JavadocAllocationExpression expression, BlockScope scope) {
+ visitor.endVisit(expression);
+ }
+ public void endVisit(JavadocAllocationExpression expression, ClassScope scope) {
+ visitor.endVisit(expression);
+ }
+ public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
+ visitor.endVisit(expression);
+ }
+ public void endVisit(JavadocArgumentExpression expression, ClassScope scope) {
+ visitor.endVisit(expression);
+ }
+ public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocArrayQualifiedTypeReference typeRef, ClassScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocArraySingleTypeReference typeRef, ClassScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
+ visitor.endVisit(fieldRef);
+ }
+ public void endVisit(JavadocFieldReference fieldRef, ClassScope scope) {
+ visitor.endVisit(fieldRef);
+ }
+ public void endVisit(JavadocImplicitTypeReference implicitTypeReference, BlockScope scope) {
+ visitor.endVisit(implicitTypeReference);
+ }
+ public void endVisit(JavadocImplicitTypeReference implicitTypeReference, ClassScope scope) {
+ visitor.endVisit(implicitTypeReference);
+ }
+ public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
+ visitor.endVisit(messageSend);
+ }
+ public void endVisit(JavadocMessageSend messageSend, ClassScope scope) {
+ visitor.endVisit(messageSend);
+ }
+ public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocQualifiedTypeReference typeRef, ClassScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
+ visitor.endVisit(statement);
+ }
+ public void endVisit(JavadocReturnStatement statement, ClassScope scope) {
+ visitor.endVisit(statement);
+ }
+ public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
+ visitor.endVisit(argument);
+ }
+ public void endVisit(JavadocSingleNameReference argument, ClassScope scope) {
+ visitor.endVisit(argument);
+ }
+ public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(JavadocSingleTypeReference typeRef, ClassScope scope) {
+ visitor.endVisit(typeRef);
+ }
+ public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
+ visitor.endVisit(labeledStatement);
+ }
+ public void endVisit(LocalDeclaration localDeclaration, BlockScope scope) {
+ visitor.endVisit(localDeclaration);
+ }
+ public void endVisit(ListExpression listDeclaration, BlockScope scope) {
+ visitor.endVisit(listDeclaration);
+ }
+ public void endVisit(MessageSend messageSend, BlockScope scope) {
+ visitor.endVisit(messageSend);
+ }
+ public void endVisit(MethodDeclaration methodDeclaration, Scope scope) {
+ visitor.endVisit(methodDeclaration);
+ }
+ public void endVisit(StringLiteralConcatenation literal, BlockScope scope) {
+ visitor.endVisit(literal);
+ }
+ public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
+ visitor.endVisit(nullLiteral);
+ }
+ public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+ visitor.endVisit(or_or_Expression);
+ }
+ public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
+ visitor.endVisit(postfixExpression);
+ }
+ public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
+ visitor.endVisit(prefixExpression);
+ }
+ public void endVisit(
+ QualifiedAllocationExpression qualifiedAllocationExpression,
+ BlockScope scope) {
+ visitor.endVisit(qualifiedAllocationExpression);
+ }
+ public void endVisit(
+ QualifiedNameReference qualifiedNameReference,
+ BlockScope scope) {
+ visitor.endVisit(qualifiedNameReference);
+ }
+ public void endVisit(
+ QualifiedNameReference qualifiedNameReference,
+ ClassScope scope) {
+ visitor.endVisit(qualifiedNameReference);
+ }
+ public void endVisit(
+ QualifiedThisReference qualifiedThisReference,
+ BlockScope scope) {
+ visitor.endVisit(qualifiedThisReference);
+ }
+ public void endVisit(
+ QualifiedThisReference qualifiedThisReference,
+ ClassScope scope) {
+ visitor.endVisit(qualifiedThisReference);
+ }
+ public void endVisit(
+ QualifiedTypeReference qualifiedTypeReference,
+ BlockScope scope) {
+ visitor.endVisit(qualifiedTypeReference);
+ }
+ public void endVisit(
+ QualifiedTypeReference qualifiedTypeReference,
+ ClassScope scope) {
+ visitor.endVisit(qualifiedTypeReference);
+ }
+
+ public void endVisit(RegExLiteral stringLiteral, BlockScope scope) {
+ visitor.endVisit(stringLiteral);
+ }
+
+
+ public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
+ visitor.endVisit(returnStatement);
+ }
+ public void endVisit(
+ SingleNameReference singleNameReference,
+ BlockScope scope) {
+ visitor.endVisit(singleNameReference);
+ }
+ public void endVisit(
+ SingleNameReference singleNameReference,
+ ClassScope scope) {
+ visitor.endVisit(singleNameReference);
+ }
+ public void endVisit(
+ SingleTypeReference singleTypeReference,
+ BlockScope scope) {
+ visitor.endVisit(singleTypeReference);
+ }
+ public void endVisit(
+ SingleTypeReference singleTypeReference,
+ ClassScope scope) {
+ visitor.endVisit(singleTypeReference);
+ }
+ public void endVisit(StringLiteral stringLiteral, BlockScope scope) {
+ visitor.endVisit(stringLiteral);
+ }
+ public void endVisit(SuperReference superReference, BlockScope scope) {
+ visitor.endVisit(superReference);
+ }
+ public void endVisit(SwitchStatement switchStatement, BlockScope scope) {
+ visitor.endVisit(switchStatement);
+ }
+
+ public void endVisit(ThisReference thisReference, BlockScope scope) {
+ visitor.endVisit(thisReference);
+ }
+ public void endVisit(ThisReference thisReference, ClassScope scope) {
+ visitor.endVisit(thisReference);
+ }
+ public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
+ visitor.endVisit(throwStatement);
+ }
+ public void endVisit(TrueLiteral trueLiteral, BlockScope scope) {
+ visitor.endVisit(trueLiteral);
+ }
+ public void endVisit(TryStatement tryStatement, BlockScope scope) {
+ visitor.endVisit(tryStatement);
+ }
+ public void endVisit(
+ TypeDeclaration localTypeDeclaration,
+ BlockScope scope) {
+ visitor.endVisit(localTypeDeclaration);
+ }
+ public void endVisit(
+ TypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ visitor.endVisit(memberTypeDeclaration);
+ }
+ public void endVisit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ visitor.endVisit(typeDeclaration);
+ }
+ public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
+ visitor.endVisit(unaryExpression);
+ }
+ public void endVisit(UndefinedLiteral undefinedLiteral, BlockScope scope) {
+ visitor.endVisit(undefinedLiteral);
+ }
+
+ public void endVisit(WhileStatement whileStatement, BlockScope scope) {
+ visitor.endVisit(whileStatement);
+ }
+ public void endVisit(WithStatement whileStatement, BlockScope scope) {
+ visitor.endVisit(whileStatement);
+ }
+ public boolean visit(
+ AllocationExpression allocationExpression,
+ BlockScope scope) {
+ return visitor.visit(allocationExpression);
+ }
+ public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+ return visitor.visit(and_and_Expression);
+ }
+ public boolean visit(Argument argument, BlockScope scope) {
+ return visitor.visit(argument);
+ }
+ public boolean visit(Argument argument, ClassScope scope) {
+ return visitor.visit(argument);
+ }
+ public boolean visit(
+ ArrayAllocationExpression arrayAllocationExpression,
+ BlockScope scope) {
+ return visitor.visit(arrayAllocationExpression);
+ }
+ public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+ return visitor.visit(arrayInitializer);
+ }
+ public boolean visit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ BlockScope scope) {
+ return visitor.visit(arrayQualifiedTypeReference);
+ }
+ public boolean visit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ ClassScope scope) {
+ return visitor.visit(arrayQualifiedTypeReference);
+ }
+ public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+ return visitor.visit(arrayReference);
+ }
+ public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ return visitor.visit(arrayTypeReference);
+ }
+ public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ return visitor.visit(arrayTypeReference);
+ }
+ public boolean visit(Assignment assignment, BlockScope scope) {
+ return visitor.visit(assignment);
+ }
+ public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+ return visitor.visit(binaryExpression);
+ }
+ public boolean visit(Block block, BlockScope scope) {
+ return visitor.visit(block);
+ }
+ public boolean visit(BreakStatement breakStatement, BlockScope scope) {
+ return visitor.visit(breakStatement);
+ }
+ public boolean visit(CaseStatement caseStatement, BlockScope scope) {
+ return visitor.visit(caseStatement);
+ }
+
+ public boolean visit(
+ CompilationUnitDeclaration compilationUnitDeclaration,
+ CompilationUnitScope scope) {
+ return visitor.visit(compilationUnitDeclaration);
+ }
+ public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
+ return visitor.visit(compoundAssignment);
+ }
+ public boolean visit(
+ ConditionalExpression conditionalExpression,
+ BlockScope scope) {
+ return visitor.visit(conditionalExpression);
+ }
+ public boolean visit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+ return visitor.visit(constructorDeclaration);
+ }
+ public boolean visit(ContinueStatement continueStatement, BlockScope scope) {
+ return visitor.visit(continueStatement);
+ }
+ public boolean visit(DoStatement doStatement, BlockScope scope) {
+ return visitor.visit(doStatement);
+ }
+ public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+ return visitor.visit(doubleLiteral);
+ }
+ public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+ return visitor.visit(emptyStatement);
+ }
+ public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+ return visitor.visit(equalExpression);
+ }
+ public boolean visit(
+ ExplicitConstructorCall explicitConstructor,
+ BlockScope scope) {
+ return visitor.visit(explicitConstructor);
+ }
+ public boolean visit(
+ ExtendedStringLiteral extendedStringLiteral,
+ BlockScope scope) {
+ return visitor.visit(extendedStringLiteral);
+ }
+ public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+ return visitor.visit(falseLiteral);
+ }
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ return visitor.visit(fieldDeclaration);
+ }
+ public boolean visit(FieldReference fieldReference, BlockScope scope) {
+ return visitor.visit(fieldReference);
+ }
+ public boolean visit(FieldReference fieldReference, ClassScope scope) {
+ return visitor.visit(fieldReference);
+ }
+ public boolean visit(ForeachStatement forStatement, BlockScope scope) {
+ return visitor.visit(forStatement);
+ }
+ public boolean visit(ForInStatement forInStatement, BlockScope scope) {
+ return visitor.visit(forInStatement);
+ }
+ public boolean visit(ForStatement forStatement, BlockScope scope) {
+ return visitor.visit(forStatement);
+ }
+ public boolean visit(FunctionExpression functionExpression, BlockScope scope) {
+ return visitor.visit(functionExpression);
+ }
+ public boolean visit(IfStatement ifStatement, BlockScope scope) {
+ return visitor.visit(ifStatement);
+ }
+ public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
+ return visitor.visit(importRef);
+ }
+
+ public boolean visit(InferredType inferredType, BlockScope scope) {
+ return visitor.visit(inferredType);
+ }
+
+ public boolean visit(InferredMethod inferredMethod, BlockScope scope) {
+ return visitor.visit(inferredMethod);
+ }
+
+ public boolean visit(InferredAttribute inferredField, BlockScope scope) {
+ return visitor.visit(inferredField);
+ }
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ return visitor.visit(initializer);
+ }
+ public boolean visit(
+ InstanceOfExpression instanceOfExpression,
+ BlockScope scope) {
+ return visitor.visit(instanceOfExpression);
+ }
+ public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+ return visitor.visit(intLiteral);
+ }
+ public boolean visit(Javadoc javadoc, BlockScope scope) {
+ return visitor.visit(javadoc);
+ }
+ public boolean visit(Javadoc javadoc, ClassScope scope) {
+ return visitor.visit(javadoc);
+ }
+ public boolean visit(JavadocAllocationExpression expression, BlockScope scope) {
+ return visitor.visit(expression);
+ }
+ public boolean visit(JavadocAllocationExpression expression, ClassScope scope) {
+ return visitor.visit(expression);
+ }
+ public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
+ return visitor.visit(expression);
+ }
+ public boolean visit(JavadocArgumentExpression expression, ClassScope scope) {
+ return visitor.visit(expression);
+ }
+ public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocArrayQualifiedTypeReference typeRef, ClassScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocArraySingleTypeReference typeRef, ClassScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
+ return visitor.visit(fieldRef);
+ }
+ public boolean visit(JavadocFieldReference fieldRef, ClassScope scope) {
+ return visitor.visit(fieldRef);
+ }
+ public boolean visit(JavadocImplicitTypeReference implicitTypeReference, BlockScope scope) {
+ return visitor.visit(implicitTypeReference);
+ }
+ public boolean visit(JavadocImplicitTypeReference implicitTypeReference, ClassScope scope) {
+ return visitor.visit(implicitTypeReference);
+ }
+ public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
+ return visitor.visit(messageSend);
+ }
+ public boolean visit(JavadocMessageSend messageSend, ClassScope scope) {
+ return visitor.visit(messageSend);
+ }
+ public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocQualifiedTypeReference typeRef, ClassScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
+ return visitor.visit(statement);
+ }
+ public boolean visit(JavadocReturnStatement statement, ClassScope scope) {
+ return visitor.visit(statement);
+ }
+ public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
+ return visitor.visit(argument);
+ }
+ public boolean visit(JavadocSingleNameReference argument, ClassScope scope) {
+ return visitor.visit(argument);
+ }
+ public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(JavadocSingleTypeReference typeRef, ClassScope scope) {
+ return visitor.visit(typeRef);
+ }
+ public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+ return visitor.visit(labeledStatement);
+ }
+ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+ return visitor.visit(localDeclaration);
+ }
+ public boolean visit(ListExpression listDeclaration, BlockScope scope) {
+ return visitor.visit(listDeclaration);
+ }
+ public boolean visit(MessageSend messageSend, BlockScope scope) {
+ return visitor.visit(messageSend);
+ }
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ return visitor.visit(methodDeclaration);
+ }
+ public boolean visit(
+ StringLiteralConcatenation literal,
+ BlockScope scope) {
+ return visitor.visit(literal);
+ }
+ public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+ return visitor.visit(nullLiteral);
+ }
+ public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+ return visitor.visit(or_or_Expression);
+ }
+ public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
+ return visitor.visit(postfixExpression);
+ }
+ public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+ return visitor.visit(prefixExpression);
+ }
+ public boolean visit(
+ QualifiedAllocationExpression qualifiedAllocationExpression,
+ BlockScope scope) {
+ return visitor.visit(qualifiedAllocationExpression);
+ }
+ public boolean visit(
+ QualifiedNameReference qualifiedNameReference,
+ BlockScope scope) {
+ return visitor.visit(qualifiedNameReference);
+ }
+ public boolean visit(
+ QualifiedNameReference qualifiedNameReference,
+ ClassScope scope) {
+ return visitor.visit(qualifiedNameReference);
+ }
+ public boolean visit(
+ QualifiedThisReference qualifiedThisReference,
+ BlockScope scope) {
+ return visitor.visit(qualifiedThisReference);
+ }
+ public boolean visit(
+ QualifiedThisReference qualifiedThisReference,
+ ClassScope scope) {
+ return visitor.visit(qualifiedThisReference);
+ }
+ public boolean visit(
+ QualifiedTypeReference qualifiedTypeReference,
+ BlockScope scope) {
+ return visitor.visit(qualifiedTypeReference);
+ }
+ public boolean visit(
+ QualifiedTypeReference qualifiedTypeReference,
+ ClassScope scope) {
+ return visitor.visit(qualifiedTypeReference);
+ }
+ public boolean visit(RegExLiteral stringLiteral, BlockScope scope) {
+ return visitor.visit(stringLiteral);
+ }
+ public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
+ return visitor.visit(returnStatement);
+ }
+ public boolean visit(
+ SingleNameReference singleNameReference,
+ BlockScope scope) {
+ return visitor.visit(singleNameReference);
+ }
+ public boolean visit(
+ SingleNameReference singleNameReference,
+ ClassScope scope) {
+ return visitor.visit(singleNameReference);
+ }
+ public boolean visit(
+ SingleTypeReference singleTypeReference,
+ BlockScope scope) {
+ return visitor.visit(singleTypeReference);
+ }
+ public boolean visit(
+ SingleTypeReference singleTypeReference,
+ ClassScope scope) {
+ return visitor.visit(singleTypeReference);
+ }
+ public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+ return visitor.visit(stringLiteral);
+ }
+ public boolean visit(SuperReference superReference, BlockScope scope) {
+ return visitor.visit(superReference);
+ }
+ public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
+ return visitor.visit(switchStatement);
+ }
+
+ public boolean visit(ThisReference thisReference, BlockScope scope) {
+ return visitor.visit(thisReference);
+ }
+ public boolean visit(ThisReference thisReference, ClassScope scope) {
+ return visitor.visit(thisReference);
+ }
+ public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
+ return visitor.visit(throwStatement);
+ }
+ public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+ return visitor.visit(trueLiteral);
+ }
+ public boolean visit(TryStatement tryStatement, BlockScope scope) {
+ return visitor.visit(tryStatement);
+ }
+ public boolean visit(
+ TypeDeclaration localTypeDeclaration,
+ BlockScope scope) {
+ return visitor.visit(localTypeDeclaration);
+ }
+ public boolean visit(
+ TypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ return visitor.visit(memberTypeDeclaration);
+ }
+ public boolean visit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ return visitor.visit(typeDeclaration);
+ }
+ public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+ return visitor.visit(unaryExpression);
+ }
+ public boolean visit(UndefinedLiteral undefined, BlockScope scope) {
+ return visitor.visit(undefined);
+ }
+ public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+ return visitor.visit(whileStatement);
+ }
+ public boolean visit(WithStatement whileStatement, BlockScope scope) {
+ return visitor.visit(whileStatement);
+ }
+ public boolean visit(ObjectLiteral literal, BlockScope scope) {
+ return visitor.visit(literal);
+ }
+ public void endVisit(ObjectLiteral literal, BlockScope scope) {
+ visitor.endVisit(literal);
+ }
+ public boolean visit(ObjectLiteralField field, BlockScope scope) {
+ return visitor.visit(field);
+ }
+ public void endVisit(ObjectLiteralField field, BlockScope scope) {
+ visitor.endVisit(field);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ICompilerRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ICompilerRequestor.java
new file mode 100644
index 0000000..629d077
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ICompilerRequestor.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+/**
+ * A callback interface for receiving compilation results.
+ */
+public interface ICompilerRequestor {
+
+ /**
+ * Accept a compilation result.
+ */
+ public void acceptResult(CompilationResult result);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IDebugRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IDebugRequestor.java
new file mode 100644
index 0000000..dd75ed3
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IDebugRequestor.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+public interface IDebugRequestor {
+
+ /*
+ * Debug callback method allowing to take into account a new compilation result.
+ * Any side-effect performed on the actual result might interfere with the
+ * original compiler requestor, and should be prohibited.
+ */
+ void acceptDebugResult(CompilationResult result);
+
+ /*
+ * Answers true when in active mode
+ */
+ boolean isActive();
+
+ /*
+ * Activate debug callbacks
+ */
+ void activate();
+
+ /*
+ * Deactivate debug callbacks
+ */
+ void deactivate();
+
+ /*
+ * Reset debug requestor after compilation has finished
+ */
+ void reset();
+}
+
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IErrorHandlingPolicy.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IErrorHandlingPolicy.java
new file mode 100644
index 0000000..cdc19e6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IErrorHandlingPolicy.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+/*
+ * Handler policy is responsible to answer the 2 following
+ * questions:
+ * 1. should the handler stop on first problem which appears
+ * to be a real error (that is, not a warning),
+ * 2. should it proceed once it has gathered all problems
+ *
+ * The intent is that one can supply its own policy to implement
+ * some interactive error handling strategy where some UI would
+ * display problems and ask user if he wants to proceed or not.
+ */
+
+public interface IErrorHandlingPolicy {
+ boolean proceedOnErrors();
+ boolean stopOnFirstError();
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IProblemFactory.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IProblemFactory.java
new file mode 100644
index 0000000..e185e6a
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/IProblemFactory.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import java.util.Locale;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+
+/*
+ * Factory used from inside the compiler to build the actual problems
+ * which are handed back in the compilation result.
+ *
+ * This allows sharing the internal problem representation with the environment.
+ *
+ * Note: The factory is responsible for computing and storing a localized error message.
+ */
+
+public interface IProblemFactory {
+
+ CategorizedProblem createProblem(
+ char[] originatingFileName,
+ int problemId,
+ String[] problemArguments,
+ String[] messageArguments, // shorter versions of the problemArguments
+ int severity,
+ int startPosition,
+ int endPosition,
+ int lineNumber,
+ int columnNumber);
+
+ Locale getLocale();
+
+ String getLocalizedMessage(int problemId, String[] messageArguments);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ISourceElementRequestor.java
new file mode 100644
index 0000000..d2bf417
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ISourceElementRequestor.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+
+/*
+ * Part of the source element parser responsible for building the output. It
+ * gets notified of structural information as they are detected, relying on the
+ * requestor to assemble them together, based on the notifications it got.
+ *
+ * The structural investigation includes: - package statement - import
+ * statements - top-level types: package member, member types (member types of
+ * member types...) - fields - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ *
+ * All positions are relative to the exact source fed to the parser.
+ *
+ * Elements which are complex are notified in two steps: - enter :
+ * once the element header has been identified - exit : once the
+ * element has been fully consumed
+ *
+ * other simpler elements (package, import) are read all at once: - accept
+ *
+ */
+
+public interface ISourceElementRequestor {
+
+ public static class TypeInfo {
+ public int declarationStart;
+ public int modifiers;
+ public char[] name;
+ public int nameSourceStart;
+ public int nameSourceEnd;
+ public char[] superclass;
+ public char[][] categories;
+ public boolean secondary;
+ public boolean anonymousMember;
+ }
+
+ public static class MethodInfo {
+ public boolean isConstructor;
+ public int declarationStart;
+ public int modifiers;
+ public char[] returnType;
+ public char[] name;
+ public int nameSourceStart;
+ public int nameSourceEnd;
+ public char[][] parameterTypes;
+ public char[][] parameterNames;
+ public char[][] categories;
+ }
+
+ public static class FieldInfo {
+ public int declarationStart;
+ public int modifiers;
+ public char[] type;
+ public char[] name;
+ public int nameSourceStart;
+ public int nameSourceEnd;
+ public char[][] categories;
+ }
+
+ void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition);
+
+ void acceptFieldReference(char[] fieldName, int sourcePosition);
+ /**
+ * @param declarationStart
+ * This is the position of the first character of the import
+ * keyword.
+ * @param declarationEnd
+ * This is the position of the ';' ending the import statement or
+ * the end of the comment following the import.
+ * @param tokens
+ * This are the tokens of the import like specified in the source.
+ * @param onDemand
+ * set to true if the import is an import on demand (e.g. import
+ * java.io.*). False otherwise.
+ */
+ void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand);
+
+ /*
+ * Table of line separator position. This table is passed once at the end of
+ * the parse action, so as to allow computation of normalized ranges.
+ *
+ * A line separator might corresponds to several characters in the source,
+ *
+ */
+ void acceptLineSeparatorPositions(int[] positions);
+
+ void acceptMethodReference(char[] methodName, int argCount, int sourcePosition);
+
+ void acceptProblem(CategorizedProblem problem);
+
+ void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd);
+
+ void acceptTypeReference(char[] typeName, int sourcePosition);
+
+ void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd);
+
+ void acceptUnknownReference(char[] name, int sourcePosition);
+
+ void enterCompilationUnit();
+
+ void enterConstructor(MethodInfo methodInfo);
+
+ void enterField(FieldInfo fieldInfo);
+
+ void enterInitializer(int declarationStart, int modifiers);
+
+ void enterMethod(MethodInfo methodInfo);
+
+ void enterType(TypeInfo typeInfo);
+
+ void exitCompilationUnit(int declarationEnd);
+
+ void exitConstructor(int declarationEnd);
+
+ /*
+ * initializationStart denotes the source start of the expression used for
+ * initializing the field if any (-1 if no initialization).
+ */
+ void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd);
+
+ void exitInitializer(int declarationEnd);
+
+ void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd);
+
+ void exitType(int declarationEnd);
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java
new file mode 100644
index 0000000..ea51584
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceElementParser.java
@@ -0,0 +1,1450 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * bug 242694 - Michael Spector
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.core.ast.IFunctionExpression;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.infer.InferredAttribute;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ClassLiteralAccess;
+import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Expression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.Initializer;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocMessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.JavadocSingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MessageSend;
+import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.NameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ObjectLiteral;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.ThisReference;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.env.ISourceType;
+import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.SourceTypeConverter;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.wst.jsdt.internal.compiler.util.Util;
+import org.eclipse.wst.jsdt.internal.core.util.CommentRecorderParser;
+
+/**
+ * A source element parser extracts structural and reference information
+ * from a piece of source.
+ *
+ * also see @ISourceElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+public class SourceElementParser extends CommentRecorderParser {
+
+ ISourceElementRequestor requestor;
+ ISourceType sourceType;
+ boolean reportReferenceInfo;
+ char[][] typeNames;
+ char[][] superTypeNames;
+ int nestedTypeIndex;
+ int nestedMethodIndex;
+ LocalDeclarationVisitor localDeclarationVisitor = null;
+ CompilerOptions options;
+ HashtableOfObjectToInt sourceEnds = new HashtableOfObjectToInt();
+ HashMap nodesToCategories = new HashMap(); // a map from ASTNode to char[][]
+ boolean useSourceJavadocParser = true;
+ HashtableOfObject notifiedTypes=new HashtableOfObject();
+
+
+ public static final boolean NOTIFY_LOCALS=false;
+/**
+ * An ast visitor that visits local type declarations.
+ */
+public class LocalDeclarationVisitor extends ASTVisitor {
+ ArrayList declaringTypes;
+ public void pushDeclaringType(TypeDeclaration declaringType) {
+ if (this.declaringTypes == null) {
+ this.declaringTypes = new ArrayList();
+ }
+ this.declaringTypes.add(declaringType);
+ }
+ public void popDeclaringType() {
+ this.declaringTypes.remove(this.declaringTypes.size()-1);
+ }
+ public TypeDeclaration peekDeclaringType() {
+ if (this.declaringTypes == null) return null;
+ int size = this.declaringTypes.size();
+ if (size == 0) return null;
+ return (TypeDeclaration) this.declaringTypes.get(size-1);
+ }
+ public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
+ notifySourceElementRequestor(typeDeclaration, sourceType == null, peekDeclaringType());
+ return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+ }
+ public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
+ notifySourceElementRequestor(typeDeclaration, sourceType == null, peekDeclaringType());
+ return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+ }
+
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+ notifySourceElementRequestor(methodDeclaration);
+ return false;
+ }
+}
+
+
+ /*
+ * Visitor for current context declaration.
+ *
+ * A context is defined by either the top level or a closure (function)
+ */
+ protected ASTVisitor contextDeclarationNotifier = new ASTVisitor(){
+
+ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+ if (NOTIFY_LOCALS || nestedMethodIndex==0)
+ notifySourceElementRequestor( localDeclaration, null );
+ return true;
+ }
+
+
+ /*
+ * Stop visiting here because the method opens a new context
+ */
+ public boolean visit(MethodDeclaration methodDeclaration, Scope scope) {
+
+ //only functions with names are notified
+ nestedMethodIndex++;
+ if( methodDeclaration.selector != null && methodDeclaration.selector.length > 0 )
+ notifySourceElementRequestor( methodDeclaration );
+ return false;
+ }
+
+ /**
+ * Visit assignments so that if the right hand side is a function it can be indexed
+ * with the right hand side used as the selector.
+ *
+ * @see org.eclipse.wst.jsdt.internal.compiler.ASTVisitor#visit(org.eclipse.wst.jsdt.internal.compiler.ast.Assignment, org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope)
+ */
+ public boolean visit(Assignment assignment, BlockScope scope) {
+ boolean keepVisiting = true;
+ IExpression righHandSide = assignment.getExpression();
+ if(righHandSide instanceof IFunctionExpression) {
+ IExpression leftHandSide = assignment.getLeftHandSide();
+
+ char[] selector = Util.getTypeName(leftHandSide);
+ if(selector != null) {
+ notifySourceElementRequestor(((IFunctionExpression) righHandSide).getMethodDeclaration(),
+ selector);
+ }
+
+ }
+ return keepVisiting;
+ }
+
+ public void endVisit(MethodDeclaration methodDeclaration, Scope scope) {
+ nestedMethodIndex--;
+
+ }
+
+ };
+
+public SourceElementParser(
+ final ISourceElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options,
+ boolean reportLocalDeclarations,
+ boolean optimizeStringLiterals) {
+ this(requestor, problemFactory, options, reportLocalDeclarations, optimizeStringLiterals, true/* use SourceJavadocParser */);
+}
+
+public SourceElementParser(
+ ISourceElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options,
+ boolean reportLocalDeclarations,
+ boolean optimizeStringLiterals,
+ boolean useSourceJavadocParser) {
+
+ super(
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ options,
+ problemFactory),
+ optimizeStringLiterals);
+
+ // we want to notify all syntax error with the acceptProblem API
+ // To do so, we define the record method of the ProblemReporter
+ this.problemReporter = new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ options,
+ problemFactory) {
+ public void record(CategorizedProblem problem, CompilationResult unitResult, ReferenceContext context) {
+ unitResult.record(problem, context); // TODO (jerome) clients are trapping problems either through factory or requestor... is result storing needed?
+ SourceElementParser.this.requestor.acceptProblem(problem);
+ }
+ };
+ this.requestor = requestor;
+ typeNames = new char[4][];
+ superTypeNames = new char[4][];
+ nestedTypeIndex = 0;
+ this.options = options;
+ if (reportLocalDeclarations) {
+ this.localDeclarationVisitor = new LocalDeclarationVisitor();
+ }
+ // set specific javadoc parser
+ this.useSourceJavadocParser = useSourceJavadocParser;
+ if (useSourceJavadocParser) {
+ this.javadocParser = new SourceJavadocParser(this);
+ }
+}
+
+public void setRequestor(ISourceElementRequestor requestor) {
+ this.requestor = requestor;
+ notifiedTypes.clear();
+}
+
+private void acceptJavadocTypeReference(Expression expression) {
+ if (expression instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) expression;
+ this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
+ } else if (expression instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) expression;
+ this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+ }
+}
+public void addUnknownRef(NameReference nameRef) {
+ // Note that:
+ // - the only requestor interested in references is the SourceIndexerRequestor
+ // - a name reference can become a type reference only during the cast case, it is then tagged later with the Binding.TYPE bit
+ // However since the indexer doesn't make the distinction between name reference and type reference, there is no need
+ // to report a type reference in the SourceElementParser.
+ // This gained 3.7% in the indexing performance test.
+ if (nameRef instanceof SingleNameReference) {
+ requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+ } else {
+ //QualifiedNameReference
+ requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
+ }
+}
+public void checkComment() {
+ // discard obsolete comments while inside methods or fields initializer (see bug 74369)
+ // don't discard if the expression being worked on is an ObjectLiteral (see bug 322412 )
+ if (!(this.diet && this.dietInt == 0) && this.scanner.commentPtr >= 0 && !(expressionPtr >= 0 && expressionStack[expressionPtr] instanceof ObjectLiteral)) {
+ flushCommentsDefinedPriorTo(this.endStatementPosition);
+ }
+
+ int lastComment = this.scanner.commentPtr;
+
+ if (this.modifiersSourceStart >= 0) {
+ // eliminate comments located after modifierSourceStart if positionned
+ while (lastComment >= 0 && Math.abs(this.scanner.commentStarts[lastComment]) > this.modifiersSourceStart) lastComment--;
+ }
+ if (lastComment >= 0) {
+ // consider all remaining leading comments to be part of current declaration
+ this.modifiersSourceStart = Math.abs(this.scanner.commentStarts[0]);
+
+ // check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)
+ while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
+ if (lastComment >= 0 && this.javadocParser != null) {
+ int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over,
+ // do not report problem before last parsed comment while recovering code...
+ this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
+ if (this.javadocParser.checkDeprecation(lastComment)) {
+ checkAndSetModifiers(ClassFileConstants.AccDeprecated);
+ }
+ this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated
+ if (currentElement == null) this.lastJavadocEnd = commentEnd;
+ }
+ }
+
+ if (this.reportReferenceInfo && this.javadocParser.checkDocComment && this.javadoc != null) {
+ // Report reference info in javadoc comment @throws/@exception tags
+ TypeReference[] thrownExceptions = this.javadoc.exceptionReferences;
+ if (thrownExceptions != null) {
+ for (int i = 0, max=thrownExceptions.length; i < max; i++) {
+ TypeReference typeRef = thrownExceptions[i];
+ if (typeRef instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+ this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
+ } else if (typeRef instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
+ this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+ }
+ }
+ }
+
+ // Report reference info in javadoc comment @see tags
+ Expression[] references = this.javadoc.seeReferences;
+ if (references != null) {
+ for (int i = 0, max=references.length; i < max; i++) {
+ Expression reference = references[i];
+ acceptJavadocTypeReference(reference);
+ if (reference instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
+ this.requestor.acceptFieldReference(fieldRef.token, fieldRef.sourceStart);
+ if (fieldRef.receiver != null && !fieldRef.receiver.isThis()) {
+ acceptJavadocTypeReference(fieldRef.receiver);
+ }
+ } else if (reference instanceof JavadocMessageSend) {
+ JavadocMessageSend messageSend = (JavadocMessageSend) reference;
+ int argCount = messageSend.arguments == null ? 0 : messageSend.arguments.length;
+ this.requestor.acceptMethodReference(messageSend.selector, argCount, messageSend.sourceStart);
+ this.requestor.acceptConstructorReference(messageSend.selector, argCount, messageSend.sourceStart);
+ if (messageSend.receiver != null && !messageSend.receiver.isThis()) {
+ acceptJavadocTypeReference(messageSend.receiver);
+ }
+ } else if (reference instanceof JavadocAllocationExpression) {
+ JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
+ int argCount = constructor.arguments == null ? 0 : constructor.arguments.length;
+ if (constructor.type != null) {
+ char[][] compoundName = constructor.type.getTypeName();
+ this.requestor.acceptConstructorReference(compoundName[compoundName.length-1], argCount, constructor.sourceStart);
+ if (!constructor.type.isThis()) {
+ acceptJavadocTypeReference(constructor.type);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+protected void classInstanceCreation(boolean alwaysQualified, boolean isShort) {
+
+ boolean previousFlag = reportReferenceInfo;
+ reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
+ super.classInstanceCreation(alwaysQualified, isShort);
+ reportReferenceInfo = previousFlag;
+ if (reportReferenceInfo){
+ AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
+// TypeReference typeRef = alloc.type;
+ char [] name={};
+ if (alloc.member !=null)
+ {
+ name=Util.getTypeName(alloc.member);
+ }
+ else if (alloc.type!=null)
+ name= CharOperation.concatWith(alloc.type.getTypeName(), '.');
+
+ if (name!=null && name.length>0)
+ requestor.acceptConstructorReference(name,
+// typeRef instanceof SingleTypeReference
+// ? ((SingleTypeReference) typeRef).token
+// : CharOperation.concatWith(alloc.type.getParameterizedTypeName(), '.'),
+ alloc.arguments == null ? 0 : alloc.arguments.length,
+ alloc.sourceStart);
+ }
+}
+
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // the scanner is located after the comma or the semi-colon.
+ // we want to include the comma or the semi-colon
+ super.consumeExitVariableWithInitialization();
+ if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
+ && this.astStack[this.astPtr] instanceof FieldDeclaration) {
+ this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+ rememberCategories();
+ }
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+ super.consumeExitVariableWithoutInitialization();
+ if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
+ && astStack[astPtr] instanceof FieldDeclaration) {
+ this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+ rememberCategories();
+ }
+}
+protected void consumeCallExpressionWithSimpleName() {
+ super.consumeCallExpressionWithSimpleName();
+ FieldReference fr = (FieldReference) expressionStack[expressionPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptFieldReference(fr.token, fr.sourceStart);
+ }
+
+}
+protected void consumeMemberExpressionWithSimpleName() {
+ super.consumeMemberExpressionWithSimpleName();
+ FieldReference fr = (FieldReference) expressionStack[expressionPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptFieldReference(fr.token, fr.sourceStart);
+ }
+
+}
+protected void consumeFormalParameter(boolean isVarArgs) {
+ super.consumeFormalParameter(isVarArgs);
+
+ // Flush comments prior to this formal parameter so the declarationSourceStart of the following parameter
+ // is correctly set (see bug 80904)
+ // Note that this could be done in the Parser itself, but this would slow down all parsers, when they don't need
+ // the declarationSourceStart to be set
+ flushCommentsDefinedPriorTo(this.scanner.currentPosition);
+}
+protected void consumeMethodHeaderName(boolean isAnonymousMethod) {
+ long selectorSourcePositions = (isAnonymousMethod) ? this.lParenPos
+ :this.identifierPositionStack[this.identifierPtr];
+ int selectorSourceEnd = (int) selectorSourcePositions;
+ int currentAstPtr = this.astPtr;
+ super.consumeMethodHeaderName(isAnonymousMethod);
+ if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
+ this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+ rememberCategories();
+ }
+}
+protected void consumeCallExpressionWithArguments() {
+ super.consumeCallExpressionWithArguments();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
+ MethodDeclaration methodDeclaration = super.convertToMethodDeclaration(c, compilationResult);
+ int selectorSourceEnd = this.sourceEnds.removeKey(c);
+ if (selectorSourceEnd != -1)
+ this.sourceEnds.put(methodDeclaration, selectorSourceEnd);
+ char[][] categories = (char[][]) this.nodesToCategories.remove(c);
+ if (categories != null)
+ this.nodesToCategories.put(methodDeclaration, categories);
+
+ return methodDeclaration;
+}
+protected CompilationUnitDeclaration endParse(int act) {
+ if (compilationUnit != null) {
+ CompilationUnitDeclaration result = super.endParse(act);
+ return result;
+ } else {
+ return null;
+ }
+}
+public TypeReference getTypeReference(int dim) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions
+ */
+ int length = identifierLengthStack[identifierLengthPtr--];
+ if (length < 0) { //flag for precompiled type reference on base types
+ TypeReference ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[intPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[intPtr--];
+ } else {
+ intPtr--; // no need to use this position as it is an array
+ ref.sourceEnd = endPosition;
+ }
+ if (reportReferenceInfo){
+ requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+ }
+ return ref;
+ } else {
+ int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
+ if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+ // generic type
+ TypeReference ref = null;
+ return ref;
+ } else if (length == 1) {
+ // single variable reference
+ this.genericsLengthPtr--; // pop the 0
+ if (dim == 0) {
+ SingleTypeReference ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.token, ref.sourceStart);
+ }
+ return ref;
+ } else {
+ ArrayTypeReference ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ ref.sourceEnd = endPosition;
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.token, ref.sourceStart);
+ }
+ return ref;
+ }
+ } else {//Qualified variable reference
+ this.genericsLengthPtr--;
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
+ }
+ return ref;
+ } else {
+ ArrayQualifiedTypeReference ref =
+ new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = endPosition;
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
+ }
+ return ref;
+ }
+ }
+ }
+}
+public NameReference getUnspecifiedReference() {
+ /* build a (unspecified) NameReference which may be qualified*/
+
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ SingleNameReference ref =
+ newSingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+ } else {
+ //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ long[] positions = new long[length];
+ System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
+ QualifiedNameReference ref =
+ newQualifiedNameReference(
+ tokens,
+ positions,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+ }
+}
+public NameReference getUnspecifiedReferenceOptimized() {
+ /* build a (unspecified) NameReference which may be qualified
+ The optimization occurs for qualified reference while we are
+ certain in this case the last item of the qualified name is
+ a field access. This optimization is IMPORTANT while it results
+ that when a NameReference is build, the type checker should always
+ look for that it is not a type reference */
+
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ SingleNameReference ref =
+ newSingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ ref.bits &= ~ASTNode.RestrictiveFlagMASK;
+ ref.bits |= Binding.LOCAL | Binding.FIELD;
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+ }
+
+ //Qualified-variable-reference
+ //In fact it is variable-reference DOT field-ref , but it would result in a type
+ //conflict tha can be only reduce by making a superclass (or inetrface ) between
+ //nameReference and FiledReference or putting FieldReference under NameReference
+ //or else..........This optimisation is not really relevant so just leave as it is
+
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ long[] positions = new long[length];
+ System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
+ QualifiedNameReference ref =
+ newQualifiedNameReference(
+ tokens,
+ positions,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32),
+ // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ ref.bits &= ~ASTNode.RestrictiveFlagMASK;
+ ref.bits |= Binding.LOCAL | Binding.FIELD;
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+}
+
+protected ImportReference newImportReference(char[][] tokens, long[] positions, boolean onDemand) {
+ return new ImportReference(tokens, positions, onDemand);
+}
+protected QualifiedNameReference newQualifiedNameReference(char[][] tokens, long[] positions, int sourceStart, int sourceEnd) {
+ return new QualifiedNameReference(tokens, positions, sourceStart, sourceEnd);
+}
+protected SingleNameReference newSingleNameReference(char[] source, long positions) {
+ return new SingleNameReference(source, positions);
+}
+
+
+
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
+ if (parsedUnit == null) {
+ // when we parse a single type member declaration the compilation unit is null, but we still
+ // want to be able to notify the requestor on the created ast node
+ if (astStack[0] instanceof AbstractMethodDeclaration) {
+ notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
+ return;
+ }
+ return;
+ }
+
+ inferTypes(parsedUnit,this.options);
+
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= parsedUnit.sourceStart
+ && scanner.eofPosition >= parsedUnit.sourceEnd;
+
+ // collect the top level ast nodes
+ if (sourceType == null){
+ if (isInRange) {
+ requestor.enterCompilationUnit();
+ }
+ }
+
+ //visit each statement to notify context declarations
+ if( parsedUnit.statements != null ){
+
+ for( int i=0; iNotifies the requester of a method declaration using the {@link AbstractMethodDeclaration#selector} as the
+ * selector to notify with.
+ *
+ * @param methodDeclaration to notify the requester of
+ *
+ * @see #notifySourceElementRequestor(AbstractMethodDeclaration, char[])
+ */
+public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
+ this.notifySourceElementRequestor(methodDeclaration, methodDeclaration.selector);
+}
+
+/**
+ * Notifies the requester of a method declaration using the given selector rather then the selector set
+ * on the declaration itself.
+ *
+ * This is useful when the selector on the declaration is not set but it can be pre-determined some other way.
+ *
+ * @param methodDeclaration to notify the requester of
+ * @param selector to use when notifying the requester of the given methodDeclaration
+ */
+public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration, char[] selector) {
+
+ this.nestedMethodIndex++;
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= methodDeclaration.declarationSourceStart
+ && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
+
+ if (methodDeclaration.isClinit()) {
+ this.visitIfNeeded(methodDeclaration);
+ this.nestedMethodIndex--;
+ return;
+ }
+
+ if (methodDeclaration.isDefaultConstructor()) {
+ if (reportReferenceInfo) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+ if (constructorCall != null) {
+ switch(constructorCall.accessMode) {
+ case ExplicitConstructorCall.This :
+ requestor.acceptConstructorReference(
+ typeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ case ExplicitConstructorCall.ImplicitSuper :
+ requestor.acceptConstructorReference(
+ superTypeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ }
+ }
+ }
+ this.nestedMethodIndex--;
+ return;
+ }
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ boolean isVarArgs = false;
+ Argument[] arguments = methodDeclaration.arguments;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ for (int i = 0; i < argumentLength; i++) {
+ if (arguments[i].type!=null) {
+ argumentTypes[i] = CharOperation.concatWith(arguments[i].type.getTypeName(), '.');
+ } else if(arguments[i].inferredType != null) {
+ argumentTypes[i] = arguments[i].inferredType.getName();
+ }
+ argumentNames[i] = arguments[i].name;
+ }
+ isVarArgs = arguments[argumentLength-1].isVarArgs();
+ }
+ // by default no selector end position
+ int selectorSourceEnd = -1;
+ if (methodDeclaration.isConstructor()) {
+ selectorSourceEnd = this.sourceEnds.get(methodDeclaration);
+ if (isInRange){
+ int currentModifiers = methodDeclaration.modifiers;
+ if (isVarArgs)
+ currentModifiers |= ClassFileConstants.AccVarargs;
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0;
+
+ ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo();
+ methodInfo.isConstructor = true;
+ methodInfo.declarationStart = methodDeclaration.declarationSourceStart;
+ methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
+ methodInfo.name = selector;
+ methodInfo.nameSourceStart = methodDeclaration.sourceStart;
+ methodInfo.nameSourceEnd = selectorSourceEnd;
+ methodInfo.parameterTypes = argumentTypes;
+ methodInfo.parameterNames = argumentNames;
+ methodInfo.categories = (char[][]) this.nodesToCategories.get(methodDeclaration);
+ requestor.enterConstructor(methodInfo);
+ }
+ /* need this check because a constructor could have been made a constructor after the
+ * method declaration was created, and thus it is not a ConstructorDeclaration
+ */
+ if (reportReferenceInfo && methodDeclaration instanceof ConstructorDeclaration) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+ if (constructorCall != null) {
+ switch(constructorCall.accessMode) {
+ case ExplicitConstructorCall.This :
+ requestor.acceptConstructorReference(
+ typeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ case ExplicitConstructorCall.ImplicitSuper :
+ requestor.acceptConstructorReference(
+ superTypeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ }
+ }
+ }
+ this.visitIfNeeded(methodDeclaration);
+ if (isInRange){
+ requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
+ }
+ this.nestedMethodIndex--;
+ return;
+ }
+ selectorSourceEnd = this.sourceEnds.get(methodDeclaration);
+ if (isInRange) {
+ int currentModifiers = methodDeclaration.modifiers;
+ if (isVarArgs)
+ currentModifiers |= ClassFileConstants.AccVarargs;
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0;
+
+ InferredType returnType = methodDeclaration instanceof MethodDeclaration
+ ? ((MethodDeclaration) methodDeclaration).inferredType
+ : null;
+ ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo();
+ methodInfo.declarationStart = methodDeclaration.declarationSourceStart;
+ methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
+ methodInfo.returnType = returnType == null ? null : returnType.getName();
+ methodInfo.name = selector;
+ methodInfo.nameSourceStart = methodDeclaration.sourceStart;
+ methodInfo.nameSourceEnd = selectorSourceEnd;
+ methodInfo.parameterTypes = argumentTypes;
+ methodInfo.parameterNames = argumentNames;
+ methodInfo.categories = (char[][]) this.nodesToCategories.get(methodDeclaration);
+ requestor.enterMethod(methodInfo);
+ }
+
+ this.visitIfNeeded(methodDeclaration);
+
+ if (isInRange) {
+ requestor.exitMethod(methodDeclaration.declarationSourceEnd, -1, -1);
+ }
+ this.nestedMethodIndex--;
+}
+
+/*
+* Update the bodyStart of the corresponding parse node
+*/
+public void notifySourceElementRequestor(AbstractVariableDeclaration fieldDeclaration, TypeDeclaration declaringType) {
+
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= fieldDeclaration.declarationSourceStart
+ && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
+
+ switch(fieldDeclaration.getKind()) {
+ case AbstractVariableDeclaration.FIELD:
+ case AbstractVariableDeclaration.LOCAL_VARIABLE:
+ int fieldEndPosition = this.sourceEnds.get(fieldDeclaration);
+ if (fieldEndPosition == -1) {
+ // use the declaration source end by default
+ fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+ }
+ MethodDeclaration methodDeclaration = null;
+ if (isInRange) {
+ int currentModifiers = fieldDeclaration.modifiers;
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0;
+
+ if (fieldDeclaration.initialization instanceof FunctionExpression) {
+ methodDeclaration=((FunctionExpression)fieldDeclaration.initialization).methodDeclaration;
+ } else if (fieldDeclaration.initialization instanceof Assignment &&
+ ((Assignment)fieldDeclaration.initialization).getExpression() instanceof FunctionExpression) {
+
+ methodDeclaration=((FunctionExpression)((Assignment)fieldDeclaration.initialization).getExpression()).methodDeclaration;
+ }
+
+ /* if the variable declaration has a method declaration on the right hand side notify of the declaration using the variable name as the method selector
+ * else notify of a field declaration
+ */
+ if (methodDeclaration!=null) {
+ this.notifySourceElementRequestor(methodDeclaration, fieldDeclaration.getName());
+ }
+ else
+ {
+ ISourceElementRequestor.FieldInfo fieldInfo = new ISourceElementRequestor.FieldInfo();
+ fieldInfo.declarationStart = fieldDeclaration.declarationSourceStart;
+ fieldInfo.name = fieldDeclaration.name;
+ fieldInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag)
+ | ClassFileConstants.AccDeprecated
+ : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
+ fieldInfo.type = fieldDeclaration.inferredType != null ? fieldDeclaration.inferredType
+ .getName()
+ : null;
+ fieldInfo.nameSourceStart = fieldDeclaration.sourceStart;
+ fieldInfo.nameSourceEnd = fieldDeclaration.sourceEnd;
+ fieldInfo.categories = (char[][]) this.nodesToCategories
+ .get(fieldDeclaration);
+ requestor.enterField(fieldInfo);
+ //If this field is of an anonymous type, need to notify so that it shows as a child
+ if (fieldDeclaration.inferredType != null
+ && fieldDeclaration.inferredType.isAnonymous) {
+ notifySourceElementRequestor(fieldDeclaration.inferredType);
+ }
+ }
+ }
+ this.visitIfNeeded(fieldDeclaration, declaringType);
+ if (isInRange){
+ if (methodDeclaration == null) {
+ requestor.exitField(
+ // filter out initializations that are not a constant (simple check)
+ (fieldDeclaration.initialization == null
+ || fieldDeclaration.initialization instanceof ArrayInitializer
+ || fieldDeclaration.initialization instanceof AllocationExpression
+ || fieldDeclaration.initialization instanceof ArrayAllocationExpression
+ || fieldDeclaration.initialization instanceof Assignment
+ || fieldDeclaration.initialization instanceof ClassLiteralAccess
+ || fieldDeclaration.initialization instanceof MessageSend
+ || fieldDeclaration.initialization instanceof ArrayReference
+ || fieldDeclaration.initialization instanceof ThisReference) ?
+ -1 :
+ fieldDeclaration.initialization.sourceStart,
+ fieldEndPosition,
+ fieldDeclaration.declarationSourceEnd);
+
+ }
+ }
+ break;
+ case AbstractVariableDeclaration.INITIALIZER:
+ if (isInRange){
+ requestor.enterInitializer(
+ fieldDeclaration.declarationSourceStart,
+ fieldDeclaration.modifiers);
+ }
+ this.visitIfNeeded((Initializer)fieldDeclaration);
+ if (isInRange){
+ requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
+ }
+ break;
+ }
+}
+public void notifySourceElementRequestor(
+ ImportReference importReference,
+ boolean isPackage) {
+
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ importReference.tokens,
+ (importReference.bits & ASTNode.OnDemand) != 0);
+
+}
+public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType) {
+
+ if (CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, typeDeclaration.name)) return;
+
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= typeDeclaration.declarationSourceStart
+ && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
+
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+ int fieldCounter = fields == null ? 0 : fields.length;
+ int methodCounter = methods == null ? 0 : methods.length;
+ int memberTypeCounter = memberTypes == null ? 0 : memberTypes.length;
+ int fieldIndex = 0;
+ int methodIndex = 0;
+ int memberTypeIndex = 0;
+
+ if (notifyTypePresence){
+
+ int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
+ char[] implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_OBJECT;
+ if (isInRange) {
+ int currentModifiers = typeDeclaration.modifiers;
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0;
+
+ char[] superclassName;
+
+ TypeReference superclass = typeDeclaration.superclass;
+ superclassName = superclass != null ? CharOperation.concatWith(superclass.getTypeName(), '.') : null;
+
+ ISourceElementRequestor.TypeInfo typeInfo = new ISourceElementRequestor.TypeInfo();
+ typeInfo.declarationStart = typeDeclaration.declarationSourceStart;
+ typeInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
+ typeInfo.name = typeDeclaration.name;
+ typeInfo.nameSourceStart = typeDeclaration.sourceStart;
+ typeInfo.nameSourceEnd = sourceEnd(typeDeclaration);
+ typeInfo.superclass = superclassName;
+ typeInfo.categories = (char[][]) this.nodesToCategories.get(typeDeclaration);
+ typeInfo.secondary = typeDeclaration.isSecondary();
+ typeInfo.anonymousMember = typeDeclaration.allocation != null && typeDeclaration.allocation.enclosingInstance != null;
+ requestor.enterType(typeInfo);
+ switch (kind) {
+ case TypeDeclaration.CLASS_DECL :
+ if (superclassName != null)
+ implicitSuperclassName = superclassName;
+ break;
+ }
+ }
+ if (this.nestedTypeIndex == this.typeNames.length) {
+ // need a resize
+ System.arraycopy(this.typeNames, 0, (this.typeNames = new char[this.nestedTypeIndex * 2][]), 0, this.nestedTypeIndex);
+ System.arraycopy(this.superTypeNames, 0, (this.superTypeNames = new char[this.nestedTypeIndex * 2][]), 0, this.nestedTypeIndex);
+ }
+ this.typeNames[this.nestedTypeIndex] = typeDeclaration.name;
+ this.superTypeNames[this.nestedTypeIndex++] = implicitSuperclassName;
+ }
+ while ((fieldIndex < fieldCounter)
+ || (memberTypeIndex < memberTypeCounter)
+ || (methodIndex < methodCounter)) {
+ FieldDeclaration nextFieldDeclaration = null;
+ AbstractMethodDeclaration nextMethodDeclaration = null;
+ TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldIndex < fieldCounter) {
+ nextFieldDeclaration = fields[fieldIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodIndex < methodCounter) {
+ nextMethodDeclaration = methods[methodIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (memberTypeIndex < memberTypeCounter) {
+ nextMemberDeclaration = memberTypes[memberTypeIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ fieldIndex++;
+ notifySourceElementRequestor(nextFieldDeclaration, typeDeclaration);
+ break;
+ case 1 :
+ methodIndex++;
+ notifySourceElementRequestor(nextMethodDeclaration);
+ break;
+ case 2 :
+ memberTypeIndex++;
+ notifySourceElementRequestor(nextMemberDeclaration, true, null);
+ }
+ }
+ if (notifyTypePresence){
+ if (isInRange){
+ requestor.exitType(typeDeclaration.declarationSourceEnd);
+ }
+ nestedTypeIndex--;
+ }
+}
+public void parseCompilationUnit(
+ ICompilationUnit unit,
+ int start,
+ int end,
+ boolean fullParse) {
+
+ this.reportReferenceInfo = fullParse;
+ boolean old = diet;
+
+ try {
+ diet = true;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
+ }
+ if (this.localDeclarationVisitor != null || fullParse){
+ diet = false;
+ this.getMethodBodies(parsedUnit);
+ }
+ this.scanner.resetTo(start, end);
+ notifySourceElementRequestor(parsedUnit);
+ } catch (AbortCompilation e) {
+ // ignore this exception
+ } finally {
+ diet = old;
+ reset();
+ }
+}
+public CompilationUnitDeclaration parseCompilationUnit(
+ ICompilationUnit unit,
+ boolean fullParse) {
+
+ boolean old = diet;
+
+ try {
+ diet = DO_DIET_PARSE;
+ this.reportReferenceInfo = fullParse;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
+ }
+ int initialStart = this.scanner.initialPosition;
+ int initialEnd = this.scanner.eofPosition;
+ if (this.localDeclarationVisitor != null || fullParse){
+ diet = false;
+ this.getMethodBodies(parsedUnit);
+ }
+ this.scanner.resetTo(initialStart, initialEnd);
+
+ notifySourceElementRequestor(parsedUnit);
+ return parsedUnit;
+ } catch (AbortCompilation e) {
+ // ignore this exception
+ } finally {
+ diet = old;
+ reset();
+ }
+ return null;
+}
+public void parseTypeMemberDeclarations(
+ ISourceType type,
+ ICompilationUnit sourceUnit,
+ int start,
+ int end,
+ boolean needReferenceInfo) {
+ boolean old = diet;
+
+ CompilationResult compilationUnitResult =
+ new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
+ try {
+ diet = !needReferenceInfo;
+ reportReferenceInfo = needReferenceInfo;
+ CompilationUnitDeclaration unit =
+ SourceTypeConverter.buildCompilationUnit(
+ new ISourceType[]{type},
+ // no need for field and methods
+ // no need for member types
+ // no need for field initialization
+ SourceTypeConverter.NONE,
+ problemReporter(),
+ compilationUnitResult);
+ if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
+ return;
+ this.sourceType = type;
+ try {
+ /* automaton initialization */
+ initialize();
+ goForClassBodyDeclarations();
+ /* scanner initialization */
+ scanner.setSource(sourceUnit.getContents());
+ scanner.resetTo(start, end);
+ /* unit creation */
+ referenceContext = compilationUnit = unit;
+ /* initialize the astStacl */
+ // the compilationUnitDeclaration should contain exactly one type
+ pushOnAstStack(unit.types[0]);
+ /* run automaton */
+ parse();
+ notifySourceElementRequestor(unit);
+ } finally {
+ unit = compilationUnit;
+ compilationUnit = null; // reset parser
+ }
+ } catch (AbortCompilation e) {
+ // ignore this exception
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
+ }
+ diet = old;
+ reset();
+ }
+}
+
+public void parseTypeMemberDeclarations(
+ char[] contents,
+ int start,
+ int end) {
+
+ boolean old = diet;
+
+ try {
+ diet = true;
+
+ /* automaton initialization */
+ initialize();
+ goForClassBodyDeclarations();
+ /* scanner initialization */
+ scanner.setSource(contents);
+ scanner.recordLineSeparator = false;
+ scanner.taskTags = null;
+ scanner.taskPriorities = null;
+ scanner.resetTo(start, end);
+
+ /* unit creation */
+ referenceContext = null;
+
+ /* initialize the astStacl */
+ // the compilationUnitDeclaration should contain exactly one type
+ /* run automaton */
+ parse();
+ notifySourceElementRequestor((CompilationUnitDeclaration)null);
+ } catch (AbortCompilation e) {
+ // ignore this exception
+ } finally {
+ diet = old;
+ reset();
+ }
+}
+/*
+ * Sort the given ast nodes by their positions.
+ */
+//private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
+// int original_left = left;
+// int original_right = right;
+// ASTNode mid = sortedCollection[ left + (right - left) / 2];
+// do {
+// while (sortedCollection[left].sourceStart < mid.sourceStart) {
+// left++;
+// }
+// while (mid.sourceStart < sortedCollection[right].sourceStart) {
+// right--;
+// }
+// if (left <= right) {
+// ASTNode tmp = sortedCollection[left];
+// sortedCollection[left] = sortedCollection[right];
+// sortedCollection[right] = tmp;
+// left++;
+// right--;
+// }
+// } while (left <= right);
+// if (original_left < right) {
+// quickSort(sortedCollection, original_left, right);
+// }
+// if (left < original_right) {
+// quickSort(sortedCollection, left, original_right);
+// }
+//}
+private void rememberCategories() {
+ if (this.useSourceJavadocParser) {
+ SourceJavadocParser sourceJavadocParser = (SourceJavadocParser) this.javadocParser;
+ char[][] categories = sourceJavadocParser.categories;
+ if (categories.length > 0) {
+ this.nodesToCategories.put(this.astStack[this.astPtr], categories);
+ sourceJavadocParser.categories = CharOperation.NO_CHAR_CHAR;
+ }
+ }
+}
+private void reset() {
+ this.sourceEnds = new HashtableOfObjectToInt();
+ this.nodesToCategories = new HashMap();
+ typeNames = new char[4][];
+ superTypeNames = new char[4][];
+ nestedTypeIndex = 0;
+}
+private int sourceEnd(TypeDeclaration typeDeclaration) {
+ if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
+ QualifiedAllocationExpression allocation = typeDeclaration.allocation;
+ if (allocation.type == null) // case of enum constant body
+ return typeDeclaration.sourceEnd;
+ return allocation.type.sourceEnd;
+ } else {
+ return typeDeclaration.sourceEnd;
+ }
+}
+private void visitIfNeeded(AbstractMethodDeclaration method) {
+ if (this.localDeclarationVisitor != null
+ //&& (method.bits & ASTNode.HasLocalType) != 0) {
+ ){
+ if (method instanceof ConstructorDeclaration) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) method;
+ if (constructorDeclaration.constructorCall != null) {
+ constructorDeclaration.constructorCall.traverse(this.localDeclarationVisitor, method.scope);
+ }
+ }
+ if (method.statements != null) {
+ int statementsLength = method.statements.length;
+ for (int i = 0; i < statementsLength; i++)
+ //method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
+ method.statements[i].traverse( contextDeclarationNotifier, method.scope );
+ }
+ }
+}
+
+private void visitIfNeeded(AbstractVariableDeclaration field, TypeDeclaration declaringType) {
+ if (this.localDeclarationVisitor != null
+ && (field.bits & ASTNode.HasLocalType) != 0) {
+ if (field.initialization != null) {
+ try {
+ this.localDeclarationVisitor.pushDeclaringType(declaringType);
+ field.initialization.traverse(this.localDeclarationVisitor, (MethodScope) null);
+ } finally {
+ this.localDeclarationVisitor.popDeclaringType();
+ }
+ }
+ }
+}
+
+private void visitIfNeeded(Initializer initializer) {
+ if (this.localDeclarationVisitor != null
+ && (initializer.bits & ASTNode.HasLocalType) != 0) {
+ if (initializer.block != null) {
+ initializer.block.traverse(this.localDeclarationVisitor, null);
+ }
+ }
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceJavadocParser.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceJavadocParser.java
new file mode 100644
index 0000000..314e833
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/SourceJavadocParser.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler;
+
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.parser.JavadocParser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
+
+public class SourceJavadocParser extends JavadocParser {
+
+ // Store categories identifiers parsed in javadoc
+ int categoriesPtr = -1;
+ char[][] categories = CharOperation.NO_CHAR_CHAR;
+
+public SourceJavadocParser(Parser sourceParser) {
+ super(sourceParser);
+ this.kind = SOURCE_PARSER | TEXT_VERIF;
+}
+
+public boolean checkDeprecation(int commentPtr) {
+ this.categoriesPtr = -1;
+ boolean result = super.checkDeprecation(commentPtr);
+ if (this.categoriesPtr > -1) {
+ System.arraycopy(this.categories, 0, this.categories = new char[this.categoriesPtr+1][], 0, this.categoriesPtr+1);
+ } else {
+ this.categories = CharOperation.NO_CHAR_CHAR;
+ }
+ return result;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.AbstractCommentParser#parseIdentifierTag()
+ */
+protected boolean parseIdentifierTag(boolean report) {
+ int end = this.lineEnd+1;
+ if (super.parseIdentifierTag(report) && this.index <= end) {
+ return true;
+ }
+ return false;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.parser.JavadocParser#parseSimpleTag()
+ */
+protected void parseSimpleTag() {
+
+ // Read first char
+ // readChar() code is inlined to balance additional method call in checkDeprectation(int)
+ char first = this.source[this.index++];
+ if (first == '\\' && this.source[this.index] == 'u') {
+ int c1, c2, c3, c4;
+ int pos = this.index;
+ this.index++;
+ while (this.source[this.index] == 'u')
+ this.index++;
+ if (!(((c1 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c1 < 0)
+ || ((c2 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c2 < 0)
+ || ((c3 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c3 < 0)
+ || ((c4 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c4 < 0))) {
+ first = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ } else {
+ this.index = pos;
+ }
+ }
+
+ // switch on first tag char
+ switch (first) {
+ case 'd': // perhaps @deprecated tag?
+ if ((readChar() == 'e') &&
+ (readChar() == 'p') && (readChar() == 'r') &&
+ (readChar() == 'e') && (readChar() == 'c') &&
+ (readChar() == 'a') && (readChar() == 't') &&
+ (readChar() == 'e') && (readChar() == 'd')) {
+ // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
+ char c = readChar();
+ if (ScannerHelper.isWhitespace(c) || c == '*') {
+ this.tagValue = TAG_DEPRECATED_VALUE;
+ this.deprecated = true;
+ }
+ }
+ break;
+ }
+}
+
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AND_AND_Expression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AND_AND_Expression.java
new file mode 100644
index 0000000..1e0fae6
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AND_AND_Expression.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IAND_AND_Expression;
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+//dedicated treatment for the &&
+public class AND_AND_Expression extends BinaryExpression implements IAND_AND_Expression {
+
+ int rightInitStateIndex = -1;
+ int mergedInitStateIndex = -1;
+
+ public AND_AND_Expression(Expression left, Expression right, int operator) {
+ super(left, right, operator);
+ }
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ Constant cst = this.left.optimizedBooleanConstant();
+ boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+ boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
+
+ if (isLeftOptimizedTrue) {
+ // TRUE && anything
+ // need to be careful of scenario:
+ // (x && y) && !z, if passing the left info to the right, it would
+ // be swapped by the !
+ FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits();
+ mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
+// mergedInitStateIndex = currentScope.methodScope()
+// .recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ }
+
+ FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
+ // need to be careful of scenario:
+ // (x && y) && !z, if passing the left info to the right, it would be
+ // swapped by the !
+ FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalCopy();
+// rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);
+
+ int previousMode = rightInfo.reachMode();
+ if (isLeftOptimizedFalse) {
+ rightInfo.setReachMode(FlowInfo.UNREACHABLE);
+ }
+ rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+ FlowInfo mergedInfo = FlowInfo.conditional(
+ rightInfo.safeInitsWhenTrue(),
+ leftInfo.initsWhenFalse().unconditionalInits().mergedWith(
+ rightInfo.initsWhenFalse().setReachMode(previousMode).unconditionalInits()));
+ // reset after trueMergedInfo got extracted
+// mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ }
+
+ public boolean isCompactableOperation() {
+ return false;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ left.traverse(visitor, scope);
+ right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.AND_AND_EXPRESSION;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ASTNode.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ASTNode.java
new file mode 100644
index 0000000..da894d1
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ASTNode.java
@@ -0,0 +1,487 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Matt McCutchen
+ * Partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995.
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.DelegateASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeIds;
+
+public abstract class ASTNode implements TypeConstants, TypeIds, IASTNode {
+
+ public int sourceStart, sourceEnd;
+
+ // storage for internal flags (32 bits) BIT USAGE
+ public final static int Bit1 = 0x1; // return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
+ public final static int Bit2 = 0x2; // return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
+ public final static int Bit3 = 0x4; // return type (operator) | name reference kind (name ref)
+ public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
+ public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)
+ public final static int Bit6 = 0x20; // depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer)
+ public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
+ public final static int Bit8 = 0x80; // depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration)
+ public final static int Bit9 = 0x100; // depth (name ref, msg) | operator (operator) | is local type (type decl)
+ public final static int Bit10= 0x200; // depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
+ public final static int Bit11 = 0x400; // depth (name ref, msg) | operator (operator) | is member type (type decl)
+ public final static int Bit12 = 0x800; // depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
+ public final static int Bit13 = 0x1000; // depth (name ref, msg) | is secondary type (type decl)
+ public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
+ public final static int Bit15 = 0x4000; // is unnecessary cast (expression) | implicit this (this ref) | is varargs (type ref) | isSubRoutineEscaping (try statement) | superAccess (javadoc allocation expression/javadoc message send/javadoc return statement)
+ public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg)
+ public final static int Bit17 = 0x10000; // compound assigned (reference lhs)
+ public final static int Bit18 = 0x20000; // non null (expression) | onDemand (import reference)
+ public final static int Bit19 = 0x40000; // didResolve (parameterized qualified type ref/parameterized single type ref) | empty (javadoc return statement)
+ public final static int Bit20 = 0x80000;
+ public final static int Bit21 = 0x100000;
+ public final static int Bit22 = 0x200000; // parenthesis count (expression) | used (import reference)
+ public final static int Bit23 = 0x400000; // parenthesis count (expression)
+ public final static int Bit24 = 0x800000; // parenthesis count (expression)
+ public final static int Bit25 = 0x1000000; // parenthesis count (expression)
+ public final static int Bit26 = 0x2000000; // parenthesis count (expression)
+ public final static int Bit27 = 0x4000000; // parenthesis count (expression)
+ public final static int Bit28 = 0x8000000; // parenthesis count (expression)
+ public final static int Bit29 = 0x10000000; // parenthesis count (expression)
+ public final static int Bit30 = 0x20000000; // elseif (if statement) | try block exit (try statement) | fall-through (case statement) | ignore no effect assign (expression ref) | needScope (for statement) | isAnySubRoutineEscaping (return statement) | blockExit (synchronized statement)
+ public final static int Bit31 = 0x40000000; // local declaration reachable (local decl) | ignore raw type check (type ref) | discard entire assignment (assignment) | isSynchronized (return statement) | thenExit (if statement)
+ public final static int Bit32 = 0x80000000; // reachable (statement)
+
+ public final static long Bit32L = 0x80000000L;
+ public final static long Bit33L = 0x100000000L;
+ public final static long Bit34L = 0x200000000L;
+ public final static long Bit35L = 0x400000000L;
+ public final static long Bit36L = 0x800000000L;
+ public final static long Bit37L = 0x1000000000L;
+ public final static long Bit38L = 0x2000000000L;
+ public final static long Bit39L = 0x4000000000L;
+ public final static long Bit40L = 0x8000000000L;
+ public final static long Bit41L = 0x10000000000L;
+ public final static long Bit42L = 0x20000000000L;
+ public final static long Bit43L = 0x40000000000L;
+ public final static long Bit44L = 0x80000000000L;
+ public final static long Bit45L = 0x100000000000L;
+ public final static long Bit46L = 0x200000000000L;
+ public final static long Bit47L = 0x400000000000L;
+ public final static long Bit48L = 0x800000000000L;
+ public final static long Bit49L = 0x1000000000000L;
+ public final static long Bit50L = 0x2000000000000L;
+ public final static long Bit51L = 0x4000000000000L;
+ public final static long Bit52L = 0x8000000000000L;
+ public final static long Bit53L = 0x10000000000000L;
+ public final static long Bit54L = 0x20000000000000L;
+ public final static long Bit55L = 0x40000000000000L;
+ public final static long Bit56L = 0x80000000000000L;
+ public final static long Bit57L = 0x100000000000000L;
+ public final static long Bit58L = 0x200000000000000L;
+ public final static long Bit59L = 0x400000000000000L;
+ public final static long Bit60L = 0x800000000000000L;
+ public final static long Bit61L = 0x1000000000000000L;
+ public final static long Bit62L = 0x2000000000000000L;
+ public final static long Bit63L = 0x4000000000000000L;
+ public final static long Bit64L = 0x8000000000000000L;
+
+ public int bits = IsReachable; // reachable by default
+
+ // for operators
+ public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4;
+ public static final int OperatorSHIFT = 6; // Bit7 -> Bit12
+ public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID
+
+ // for binary expressions
+ public static final int IsReturnedValue = Bit5;
+
+ // for name references
+ public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3|Bit4;
+
+ // for name refs or local decls
+ public static final int FirstAssignmentToLocal = Bit4;
+
+ // for this reference
+ public static final int IsImplicitThis = Bit15;
+
+ // for single name references
+ public static final int DepthSHIFT = 5; // Bit6 -> Bit13
+ public static final int DepthMASK = Bit6|Bit7|Bit8|Bit9|Bit10|Bit11|Bit12|Bit13; // 8 bits for actual depth value (max. 255)
+
+ // for statements
+ public static final int IsReachable = Bit32;
+ public static final int LabelUsed = Bit7;
+ public static final int DocumentedFallthrough = Bit30;
+
+ // local decls
+ public static final int IsLocalDeclarationReachable = Bit31;
+
+ // try statements
+ public static final int IsSubRoutineEscaping = Bit15;
+ public static final int IsTryBlockExiting = Bit30;
+
+ // for type declaration
+ public static final int ContainsAssertion = Bit1;
+ public static final int IsLocalType = Bit9;
+ public static final int IsAnonymousType = Bit10; // used to test for anonymous
+ public static final int IsMemberType = Bit11; // local member do not know it is local at parse time (need to look at binding)
+ public static final int HasAbstractMethods = Bit12; // used to promote abstract enums
+ public static final int IsSecondaryType = Bit13; // used to test for secondary
+ public static final int HasBeenGenerated = Bit14;
+
+ // for type, method and field declarations
+ public static final int HasLocalType = Bit2; // cannot conflict with AddAssertionMASK
+ public static final int HasBeenResolved = Bit5; // field decl only (to handle forward references)
+
+ // for expression
+ public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29
+ public static final int ParenthesizedMASK = Bit22|Bit23|Bit24|Bit25|Bit26|Bit27|Bit28|Bit29; // 8 bits for parenthesis count value (max. 255)
+ public static final int IgnoreNoEffectAssignCheck = Bit30;
+
+ // for references on lhs of assignment
+ public static final int IsStrictlyAssigned = Bit14; // set only for true assignments, as opposed to compound ones
+ public static final int IsCompoundAssigned = Bit17; // set only for compound assignments, as opposed to other ones
+
+ // for explicit constructor call
+ public static final int DiscardEnclosingInstance = Bit14; // used for codegen
+
+ // for empty statement
+ public static final int IsUsefulEmptyStatement = Bit1;
+
+ // for block and method declaration
+ public static final int UndocumentedEmptyBlock = Bit4;
+ public static final int OverridingMethodWithSupercall = Bit5;
+
+ // for initializer and method declaration
+ public static final int ErrorInSignature = Bit6;
+
+ // for abstract method declaration
+ public static final int NeedFreeReturn = Bit7; // abstract method declaration
+
+ // for constructor declaration
+ public static final int IsDefaultConstructor = Bit8;
+
+ // for compilation unit
+ public static final int HasAllMethodBodies = Bit5;
+ public static final int IsImplicitUnit = Bit1;
+
+ // for references in Javadoc comments
+ public static final int InsideJavadoc = Bit16;
+
+ // for javadoc allocation expression/javadoc message send/javadoc return statement
+ public static final int SuperAccess = Bit15;
+
+ // for javadoc return statement
+ public static final int Empty = Bit19;
+
+ // for if statement
+ public static final int IsElseIfStatement = Bit30;
+ public static final int ThenExit = Bit31;
+
+ // for type reference
+ public static final int IsSuperType = Bit5;
+ public static final int IsVarArgs = Bit15;
+ public static final int IgnoreRawTypeCheck = Bit31;
+
+ // for array initializer
+ public static final int IsAnnotationDefaultValue = Bit1;
+
+ // for null reference analysis
+ public static final int IsNonNull = Bit18;
+
+ // for for statement
+ public static final int NeededScope = Bit30;
+
+ // for import reference
+ public static final int OnDemand = Bit18;
+ public static final int Used = Bit2;
+ public static final int IsFileImport = Bit5;
+
+ // for parameterized qualified/single type ref
+ public static final int DidResolve = Bit19;
+
+ // for return statement
+ public static final int IsAnySubRoutineEscaping = Bit30;
+
+ // for synchronized statement
+ public static final int BlockExit = Bit30;
+
+ // for method decls and var decls
+ public static final int IsInferredType = Bit14;
+ public static final int IsInferredJsDocType = Bit15;
+
+ // constants used when checking invocation arguments
+ public static final int INVOCATION_ARGUMENT_OK = 0;
+ public static final int INVOCATION_ARGUMENT_UNCHECKED = 1;
+ public static final int INVOCATION_ARGUMENT_WILDCARD = 2;
+
+ public ASTNode() {
+
+ super();
+ }
+ private static int checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType, TypeBinding originalParameterType) {
+ TypeBinding checkedParameterType = originalParameterType == null ? parameterType : originalParameterType;
+ if (argumentType != checkedParameterType && argumentType.needsUncheckedConversion(checkedParameterType)) {
+ return INVOCATION_ARGUMENT_UNCHECKED;
+ }
+ return INVOCATION_ARGUMENT_OK;
+ }
+ public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
+ TypeBinding[] params = method.parameters;
+ int paramLength = params.length;
+
+ int invocationStatus = INVOCATION_ARGUMENT_OK;
+ if (arguments != null) {
+ if (method.isVarargs()) {
+ // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
+ int lastIndex = paramLength - 1;
+ for (int i = 0; i < lastIndex; i++) {
+ TypeBinding originalRawParam = null;
+ invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i] , argumentTypes[i], originalRawParam);
+ }
+ int argLength = arguments.length;
+ if (lastIndex < argLength) { // vararg argument was provided
+ TypeBinding parameterType = params[lastIndex];
+ TypeBinding originalRawParam = null;
+
+ if (paramLength != argLength || parameterType.dimensions() != argumentTypes[lastIndex].dimensions()) {
+ parameterType = ((ArrayBinding) parameterType).elementsType(); // single element was provided for vararg parameter
+ }
+ for (int i = lastIndex; i < argLength; i++) {
+ invocationStatus |= checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i], originalRawParam);
+ }
+ }
+
+ if (paramLength == argumentTypes.length) { // 70056
+ int varargsIndex = paramLength - 1;
+ ArrayBinding varargsType = (ArrayBinding) params[varargsIndex];
+ TypeBinding lastArgType = argumentTypes[varargsIndex];
+ int dimensions;
+ if (lastArgType != TypeBinding.NULL && (varargsType.dimensions <= (dimensions = lastArgType.dimensions()))) {
+ if (lastArgType.leafComponentType().isBaseType()) {
+ dimensions--;
+ }
+ }
+ }
+ } else {
+ int length = (paramLength 0; i--) output.append(" "); //$NON-NLS-1$
+ return output;
+ }
+
+ public static StringBuffer printModifiers(int modifiers, StringBuffer output) {
+
+ if ((modifiers & ClassFileConstants.AccPublic) != 0)
+ output.append("public "); //$NON-NLS-1$
+ if ((modifiers & ClassFileConstants.AccPrivate) != 0)
+ output.append("private "); //$NON-NLS-1$
+ if ((modifiers & ClassFileConstants.AccProtected) != 0)
+ output.append("protected "); //$NON-NLS-1$
+ if ((modifiers & ClassFileConstants.AccStatic) != 0)
+ output.append("static "); //$NON-NLS-1$
+ if ((modifiers & ClassFileConstants.AccFinal) != 0)
+ output.append("final "); //$NON-NLS-1$
+ if ((modifiers & ClassFileConstants.AccNative) != 0)
+ output.append("native "); //$NON-NLS-1$
+ if ((modifiers & ClassFileConstants.AccAbstract) != 0)
+ output.append("abstract "); //$NON-NLS-1$
+ return output;
+ }
+
+ public int sourceStart() {
+ return this.sourceStart;
+ }
+ public int sourceEnd() {
+ return this.sourceEnd;
+ }
+ public void setSourceEnd(int pos) {
+ this.sourceEnd = pos;
+ }
+ public String toString() {
+ return print(0, new StringBuffer(30)).toString();
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ // do nothing by default
+ }
+
+ public boolean isInferred() {
+ return false;
+ }
+ public int getASTType() {
+ return IASTNode.AST_NODE;
+
+ }
+
+ public void traverse(org.eclipse.wst.jsdt.core.ast.ASTVisitor visitor) {
+ this.traverse(new DelegateASTVisitor(visitor), null);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java
new file mode 100644
index 0000000..b0f2648
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -0,0 +1,432 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IAbstractFunctionDeclaration;
+import org.eclipse.wst.jsdt.core.ast.IArgument;
+import org.eclipse.wst.jsdt.core.ast.IJsDoc;
+import org.eclipse.wst.jsdt.core.ast.IProgramElement;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortMethod;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortType;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
+
+
+public abstract class AbstractMethodDeclaration extends Statement
+ implements IAbstractFunctionDeclaration, ProblemSeverities, ReferenceContext {
+
+ public MethodScope scope;
+ private MethodScope prevScope;
+ //it is not relevent for constructor but it helps to have the name of the constructor here
+ //which is always the name of the class.....parsing do extra work to fill it up while it do not have to....
+ public char[] selector;
+ public char[] potentialName;
+ public int declarationSourceStart;
+ public int declarationSourceEnd;
+ public int modifiers;
+ public Argument[] arguments;
+ public Statement[] statements;
+ public int explicitDeclarations;
+ public MethodBinding binding;
+ public boolean ignoreFurtherInvestigation = false;
+ public boolean needFreeReturn = false;
+ public boolean resolveChildStatments = true;
+
+ public Javadoc javadoc;
+
+ public int bodyStart;
+ public int bodyEnd = -1;
+ public CompilationResult compilationResult;
+
+ public InferredType inferredType;
+ public InferredMethod inferredMethod;
+
+ public boolean errorInSignature = false;
+ public int exprStackPtr;
+
+ AbstractMethodDeclaration(CompilationResult compilationResult){
+ this.compilationResult = compilationResult;
+ this.prevScope = null;
+ }
+
+ public void setArguments( IArgument[] args) {
+ if(args instanceof Argument[]) this.arguments = (Argument[])args;
+ }
+
+ public IArgument[] getArguments() {
+ return this.arguments;
+ }
+
+ /*
+ * We cause the compilation task to abort to a given extent.
+ */
+ public void abort(int abortLevel, CategorizedProblem problem) {
+
+ switch (abortLevel) {
+ case AbortCompilation :
+ throw new AbortCompilation(this.compilationResult, problem);
+ case AbortCompilationUnit :
+ throw new AbortCompilationUnit(this.compilationResult, problem);
+ case AbortType :
+ throw new AbortType(this.compilationResult, problem);
+ default :
+ throw new AbortMethod(this.compilationResult, problem);
+ }
+ }
+
+ public FlowInfo analyseCode(BlockScope classScope, FlowContext initializationContext, FlowInfo info)
+ {
+ return this.analyseCode((Scope)classScope, initializationContext, info);
+ }
+
+ public abstract FlowInfo analyseCode(Scope classScope, FlowContext initializationContext, FlowInfo info);
+
+ /**
+ * Bind and add argument's binding into the scope of the method
+ */
+ public void bindArguments() {
+ //only bind arguments if the current scope does not equal the scope last used to bind args
+ if (this.arguments != null && (this.prevScope == null || this.prevScope != this.scope)) {
+ this.prevScope = this.scope;
+
+ // by default arguments in abstract/native methods are considered to be used (no complaint is expected)
+ if (this.binding == null) {
+ for (int i = 0, length = this.arguments.length; i < length; i++) {
+ this.arguments[i].bind(this.scope, null, true);
+ }
+ return;
+ }
+ if (this.arguments.length>0 && this.binding.parameters.length==0) // types not set yet
+ {
+ ReferenceBinding declaringClass = this.binding.declaringClass;
+ if (declaringClass instanceof SourceTypeBinding) {
+ SourceTypeBinding binding = (SourceTypeBinding) declaringClass;
+ binding.resolveTypesFor(this.binding,this);
+ }
+ }
+ boolean used = this.binding.isAbstract();
+ for (int i = 0, length = this.arguments.length; i < length && i < this.binding.parameters.length; i++) {
+ IArgument argument = this.arguments[i];
+ argument.bind(this.scope, this.binding.parameters[i], used);
+ }
+ }
+ }
+
+ public CompilationResult compilationResult() {
+
+ return this.compilationResult;
+ }
+
+ public boolean hasErrors() {
+ return this.ignoreFurtherInvestigation;
+ }
+
+ public boolean isAbstract() {
+
+ if (this.binding != null)
+ return this.binding.isAbstract();
+ return (this.modifiers & ClassFileConstants.AccAbstract) != 0;
+ }
+
+ public boolean isClinit() {
+
+ return false;
+ }
+
+
+ /**
+ * @return If the {@link #inferredMethod} is set then use that to determine if
+ * this declaration is a constructor, else false
+ */
+ public boolean isConstructor() {
+ boolean isConstructor = false;
+ if(this.inferredMethod != null) {
+ isConstructor = this.inferredMethod.isConstructor;
+ }
+ return isConstructor;
+ }
+
+ public boolean isDefaultConstructor() {
+
+ return false;
+ }
+
+ public boolean isInitializationMethod() {
+
+ return false;
+ }
+
+ public boolean isMethod() {
+
+ return false;
+ }
+
+ public boolean isStatic() {
+
+ if (this.binding != null)
+ return this.binding.isStatic();
+ return (this.modifiers & ClassFileConstants.AccStatic) != 0;
+ }
+
+ public boolean isInferredJsDocType() {
+ return (this.bits & ASTNode.IsInferredJsDocType) != 0;
+ }
+
+ /**
+ * Fill up the method body with statement
+ * @param parser
+ * @param unit
+ */
+ public abstract void parseStatements(
+ Parser parser,
+ CompilationUnitDeclaration unit);
+
+ public StringBuffer printStatement(int indent, StringBuffer output)
+ {
+ return print(indent,output);
+ }
+
+ public StringBuffer print(int tab, StringBuffer output) {
+
+ if (this.javadoc != null) {
+ this.javadoc.print(tab, output);
+ }
+ printIndent(tab, output);
+
+ output.append("function "); //$NON-NLS-1$
+ if (this.selector!=null)
+ output.append(this.selector);
+ output.append('(');
+ if (this.arguments != null) {
+ for (int i = 0; i < this.arguments.length; i++) {
+ if (i > 0) output.append(", "); //$NON-NLS-1$
+ this.arguments[i].print(0, output);
+ }
+ }
+ output.append(')');
+ printBody(tab + 1, output);
+ return output;
+ }
+
+ public StringBuffer printBody(int indent, StringBuffer output) {
+
+ if (isAbstract() || (this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
+ return output.append(';');
+
+ output.append(" {"); //$NON-NLS-1$
+ if (this.statements != null) {
+ for (int i = 0; i < this.statements.length; i++) {
+ output.append('\n');
+ this.statements[i].printStatement(indent, output);
+ }
+ }
+ output.append('\n');
+ printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
+ return output;
+ }
+
+ public StringBuffer printReturnType(int indent, StringBuffer output) {
+
+ return output;
+ }
+
+ public void resolve(Scope upperScope) {
+ if (this.scope==null )
+ {
+ this.scope = new MethodScope(upperScope,this, false);
+ if (this.selector!=null) {
+ SourceTypeBinding compilationUnitBinding = upperScope
+ .enclosingCompilationUnit();
+ MethodBinding methodBinding = scope.createMethod(this,
+ this.selector, compilationUnitBinding, false, true);
+ if (methodBinding != null) {
+ this.binding = methodBinding;
+ methodBinding = compilationUnitBinding
+ .resolveTypesFor(methodBinding,this);
+ if (methodBinding != null) {
+ MethodScope enclosingMethodScope = upperScope
+ .enclosingMethodScope();
+ if (enclosingMethodScope != null)
+ enclosingMethodScope.addLocalMethod(methodBinding);
+ else {
+ compilationUnitBinding.addMethod(methodBinding);
+ upperScope.environment().defaultPackage.addBinding(
+ methodBinding, methodBinding.selector,
+ Binding.METHOD);
+ }
+ }
+ }
+ }
+
+ }
+
+ if (this.binding == null) {
+
+
+ this.ignoreFurtherInvestigation = true;
+ }
+
+ try {
+ if(resolveChildStatments) {
+ bindArguments();
+ resolveJavadoc();
+ resolveStatements();
+ }
+ } catch (AbortMethod e) { // ========= abort on fatal error =============
+ this.ignoreFurtherInvestigation = true;
+ }
+ }
+
+ public void resolveJavadoc() {
+
+ if (this.binding == null) return;
+ if (this.javadoc != null) {
+ this.javadoc.resolve(this.scope);
+ return;
+ }
+ if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
+ this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+ }
+ }
+
+ // made some changes here to fix https://bugs.eclipse.org/bugs/show_bug.cgi?id=262728
+ public void resolveStatements() {
+ if (this.statements != null) {
+ List hoistedDeclarations = null;
+
+ HoistingFinder hoistingFinder = new HoistingFinder();
+
+ hoistingFinder.perform(this.statements);
+ hoistedDeclarations = hoistingFinder.getDeclarations();
+
+ if (hoistedDeclarations != null)
+ {
+ for(int i = 0; i < hoistedDeclarations.size(); i++) {
+ ASTNode decl = (ASTNode) hoistedDeclarations.get(i);
+ if (decl instanceof AbstractMethodDeclaration) {
+ // if this is a function then resolve it, but store it as well
+ // we need to take a second pass later to resolve its child statements
+ // this step will put the declaration in scope
+ AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration) decl;
+ methodDecl.resolveChildStatments = false;
+ methodDecl.resolve(this.scope);
+ methodDecl.resolveChildStatments = true;
+ } else if (decl instanceof LocalDeclaration) {
+ // if this is local variable declaration then resolve it, and
+ // mark hoisted to prevent duplicated resolving
+ LocalDeclaration localDecl = (LocalDeclaration) decl;
+ localDecl.resolve(this.scope);
+ localDecl.setHoistedFlag();
+ }
+ }
+ }
+
+ // now go back and resolve the non-hoisted statements
+ // and children statements of functions.
+ for (int i = 0, length = this.statements.length; i < length; i++) {
+ this.statements[i].resolve(this.scope);
+ }
+
+ //unmark hoisted local variable delclarations
+ if (hoistedDeclarations != null)
+ {
+ for(int i = 0; i < hoistedDeclarations.size(); i++) {
+ ASTNode decl = (ASTNode) hoistedDeclarations.get(i);
+ if (decl instanceof LocalDeclaration) {
+ ((LocalDeclaration) decl).unsetHoistedFlag();
+ }
+ }
+ }
+ } else if ((this.bits & UndocumentedEmptyBlock) != 0) {
+ this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1);
+ }
+ }
+
+ public void tagAsHavingErrors() {
+ this.ignoreFurtherInvestigation = true;
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ Scope classScope) {
+ // default implementation: subclass will define it
+ }
+
+ public void resolve(BlockScope scope) {
+ this.resolve((Scope)scope);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode#isInferred()
+ */
+ public boolean isInferred() {
+ return this.inferredMethod != null;
+ }
+
+ public int getASTType() {
+ return IASTNode.ABSTRACT_FUNCTION_DECLARATION;
+
+ }
+
+ public IJsDoc getJsDoc() {
+ return this.javadoc;
+ }
+
+ public IProgramElement[] getStatements() {
+ return this.statements;
+ }
+
+ public char[] getName() {
+ return this.selector != null ? this.selector : this.potentialName;
+ }
+
+ public void setInferredType(InferredType type) {
+ this.inferredType=type;
+ }
+
+ public InferredMethod getInferredMethod() {
+ return this.inferredMethod;
+ }
+
+ public InferredType getInferredType() {
+ return this.inferredType;
+ }
+
+ public char [] getSafeName() {
+ if(this.selector != null)
+ return this.selector;
+ if(this.inferredMethod != null && this.inferredMethod.name != null)
+ return this.inferredMethod.name;
+ return new char []{};
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractVariableDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractVariableDeclaration.java
new file mode 100644
index 0000000..90d657f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IAbstractVariableDeclaration;
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.core.ast.IJsDoc;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public abstract class AbstractVariableDeclaration extends Statement implements IAbstractVariableDeclaration, InvocationSite {
+ public int declarationEnd;
+ public int declarationSourceEnd;
+ public int declarationSourceStart;
+ public int hiddenVariableDepth; // used to diagnose hiding scenarii
+ public Expression initialization;
+ public int modifiers;
+ public int modifiersSourceStart;
+ public Javadoc javadoc;
+
+
+ public InferredType inferredType;
+ public char[] name;
+
+ public TypeReference type;
+
+ public AbstractVariableDeclaration nextLocal;
+
+ public InferredType getInferredType() {
+ return this.inferredType;
+ }
+
+ public void setInferredType(InferredType type) {
+ this.inferredType = type;
+ }
+
+ public char[] getName() {
+ return this.name;
+ }
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ return flowInfo;
+ }
+
+ public static final int FIELD = 1;
+ public static final int INITIALIZER = 2;
+ public static final int LOCAL_VARIABLE = 4;
+ public static final int PARAMETER = 5;
+
+ /**
+ * Returns the constant kind of this variable declaration
+ */
+ public abstract int getKind();
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+ */
+ public boolean isSuperAccess() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite#isTypeAccess()
+ */
+ public boolean isTypeAccess() {
+ return false;
+ }
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+ printAsExpression(indent, output);
+ return output.append(';');
+ }
+
+ public StringBuffer printAsExpression(int indent, StringBuffer output) {
+ printIndent(indent, output);
+ printModifiers(this.modifiers, output);
+ output.append("var "); //$NON-NLS-1$
+
+ printFragment(indent, output);
+ if (this.nextLocal!=null)
+ {
+ output.append(", "); //$NON-NLS-1$
+ this.nextLocal.printFragment(indent, output);
+ }
+ return output;
+ }
+
+ protected void printFragment(int indent, StringBuffer output) {
+ if (type != null) {
+ type.print(0, output).append(' ');
+ }
+ output.append(this.name);
+
+ if (initialization != null) {
+ output.append(" = "); //$NON-NLS-1$
+ initialization.printExpression(indent, output);
+ }
+ }
+
+ public void resolve(BlockScope scope) {
+ // do nothing by default (redefined for local variables)
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite#setActualReceiverType(org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding)
+ */
+ public void setActualReceiverType(ReferenceBinding receiverType) {
+ // do nothing by default
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite#setDepth(int)
+ */
+ public void setDepth(int depth) {
+
+ this.hiddenVariableDepth = depth;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite#setFieldIndex(int)
+ */
+ public void setFieldIndex(int depth) {
+ // do nothing by default
+ }
+
+ public TypeBinding getTypeBinding()
+ {
+ if (type!=null)
+ return type.resolvedType;
+ else if (inferredType!=null)
+ return inferredType.binding;
+ return null;
+
+ }
+ public int getASTType() {
+ return IASTNode.ABSTRACT_VARIABLE_DECLARATION;
+
+ }
+
+ public IJsDoc getJsDoc()
+ {
+ return this.javadoc;
+ }
+
+ public IExpression getInitialization()
+ {
+ return this.initialization;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java
new file mode 100644
index 0000000..07aba58
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/AllocationExpression.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IAllocationExpression;
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemMethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+
+public class AllocationExpression extends Expression implements InvocationSite, IAllocationExpression {
+
+ public TypeReference type;
+ public Expression[] arguments;
+ public MethodBinding binding; // exact binding resulting from lookup
+ protected MethodBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor)
+ public Expression member;
+ public boolean isShort;
+
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (this.member!=null)
+ flowInfo =
+ this.member
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits();
+ // process arguments
+ if (arguments != null) {
+ for (int i = 0, count = arguments.length; i < count; i++) {
+ flowInfo =
+ arguments[i]
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits();
+ }
+ }
+
+ return flowInfo;
+ }
+
+ public Expression enclosingInstance() {
+ return null;
+ }
+
+ public boolean isSuperAccess() {
+ return false;
+ }
+
+ public boolean isTypeAccess() {
+ return true;
+ }
+
+ /* Inner emulation consists in either recording a dependency
+ * link only, or performing one level of propagation.
+ *
+ * Dependency mechanism is used whenever dealing with source target
+ * types, since by the time we reach them, we might not yet know their
+ * exact need.
+ */
+ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+ if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
+ ReferenceBinding allocatedTypeErasure = binding.declaringClass;
+
+ // perform some emulation work in case there is some and we are inside a local type only
+ if (allocatedTypeErasure.isNestedType()
+ && currentScope.enclosingSourceType().isLocalType()) {
+
+ if (allocatedTypeErasure.isLocalType()) {
+ ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false);
+ // request cascade of accesses
+ }
+ }
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append("new "); //$NON-NLS-1$
+ member.print(indent, output);
+
+ if (type != null) { // type null for enum constant initializations
+ type.printExpression(0, output);
+ }
+ if (!isShort)
+ {
+ output.append('(');
+ if (arguments != null) {
+ for (int i = 0; i < arguments.length; i++) {
+ if (i > 0) output.append(", "); //$NON-NLS-1$
+ arguments[i].printExpression(0, output);
+ }
+ }
+ output.append(')');
+ }
+ return output;
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ // Propagate the type checking to the arguments, and check if the constructor is defined.
+ constant = Constant.NotAConstant;
+ if (this.member!=null) {
+ this.resolvedType=this.member.resolveForAllocation(scope, this);
+ if (this.resolvedType!=null && !this.resolvedType.isValidBinding()) {
+ scope.problemReporter().invalidType(this, this.resolvedType);
+ }
+ }
+ else if (this.type == null) {
+ // initialization of an enum constant
+ this.resolvedType = scope.enclosingReceiverType();
+ }
+ else {
+ this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
+ }
+ // will check for null after args are resolved
+ // buffering the arguments' types
+ boolean argsContainCast = false;
+ TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
+ if (arguments != null) {
+ boolean argHasError = false;
+ int length = arguments.length;
+ argumentTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ Expression argument = this.arguments[i];
+ if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
+ argHasError = true;
+ argumentTypes[i]=TypeBinding.UNKNOWN;
+ }
+ }
+ }
+ if (this.resolvedType == null || this.resolvedType.isAnyType()|| this.resolvedType instanceof ProblemReferenceBinding)
+ {
+ this.binding= new ProblemMethodBinding(
+ TypeConstants.INIT,
+ Binding.NO_PARAMETERS,
+ ProblemReasons.NotFound);
+ this.resolvedType=TypeBinding.UNKNOWN;
+ return this.resolvedType;
+
+ }
+
+ if (!this.resolvedType.isValidBinding())
+ return null;
+ if (this.resolvedType instanceof ReferenceBinding )
+ {
+ ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
+ if (!(binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) {
+ if (binding.declaringClass == null)
+ binding.declaringClass = allocationType;
+ scope.problemReporter().invalidConstructor(this, binding);
+ return this.resolvedType;
+ }
+ if (argumentTypes.length!=binding.parameters.length)
+ scope.problemReporter().wrongNumberOfArguments(this, binding);
+ if (isMethodUseDeprecated(binding, scope, true))
+ scope.problemReporter().deprecatedMethod(binding, this);
+ checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this);
+ }
+
+ return this.resolvedType;
+ }
+
+ public void setActualReceiverType(ReferenceBinding receiverType) {
+ // ignored
+ }
+
+ public void setDepth(int i) {
+ // ignored
+ }
+
+ public void setFieldIndex(int i) {
+ // ignored
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.member!=null)
+ this.member.traverse(visitor, scope);
+ else if (this.type != null) { // enum constant scenario
+ this.type.traverse(visitor, scope);
+ }
+ if (this.arguments != null) {
+ for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++)
+ this.arguments[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.ALLOCATION_EXPRESSION;
+
+ }
+
+ public IExpression getMember() {
+ return this.member;
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolveForAllocation(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode)
+ */
+ public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) {
+ return this.resolveType(scope);
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Argument.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Argument.java
new file mode 100644
index 0000000..707b418
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Argument.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IArgument;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class Argument extends LocalDeclaration implements IArgument {
+
+ public char [] comment;
+
+ public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
+
+ super(name, (int) (posNom >>> 32), (int) posNom);
+ this.declarationSourceEnd = (int) posNom;
+ this.modifiers = modifiers;
+ type = tr;
+ this.bits |= IsLocalDeclarationReachable;
+ }
+
+ public char[] getComment() {
+ return this.comment;
+ }
+
+ public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+
+ // record the resolved type into the type reference
+
+ Binding existingVariable = scope.getLocalBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
+ if (existingVariable != null && existingVariable.isValidBinding() && existingVariable instanceof LocalVariableBinding ){
+ LocalVariableBinding localVariableBinding=(LocalVariableBinding)existingVariable;
+// if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+// scope.problemReporter().redefineArgument(this);
+// } else {
+// boolean isSpecialArgument = false;
+// if (existingVariable instanceof FieldBinding) {
+// if (scope.isInsideConstructor()) {
+// isSpecialArgument = true; // constructor argument
+// } else {
+// AbstractMethodDeclaration methodDecl = scope.referenceMethod();
+// if (methodDecl != null && CharOperation.prefixEquals(SET, methodDecl.selector)) {
+// isSpecialArgument = true; // setter argument
+// }
+// }
+// }
+ if (localVariableBinding.declaringScope.compilationUnitScope()==scope.compilationUnitScope())
+ scope.problemReporter().localVariableHiding(this, existingVariable, false);
+// }
+ }
+
+ if (this.binding == null) {
+ this.binding = new LocalVariableBinding(this, typeBinding, this.modifiers, true);
+ }
+ scope.addLocalVariable( this.binding );
+// if (JavaScriptCore.IS_ECMASCRIPT4)
+// resolveAnnotations(scope, this.annotations, this.binding);
+ //true stand for argument instead of just local
+ this.binding.declaration = this;
+ this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
+ }
+
+ /**
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+ */
+ public int getKind() {
+ return PARAMETER;
+ }
+
+ public boolean isVarArgs() {
+ return this.type != null && (this.type.bits & IsVarArgs) != 0;
+ }
+
+ public StringBuffer print(int indent, StringBuffer output) {
+
+ printIndent(indent, output);
+ printModifiers(this.modifiers, output);
+// if (this.annotations != null) printAnnotations(this.annotations, output);
+
+// if (type == null) {
+// output.append(" "); //$NON-NLS-1$
+// } else {
+// type.print(0, output).append(' ');
+// }
+ return output.append(this.name);
+ }
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+
+ return print(indent, output).append(';');
+ }
+
+ public TypeBinding resolveForCatch(BlockScope scope) {
+
+ // resolution on an argument of a catch clause
+ // provide the scope with a side effect : insertion of a LOCAL
+ // that represents the argument. The type must be from JavaThrowable
+
+ ReferenceBinding javaLangError = scope.getJavaLangError();
+ TypeBinding exceptionType = this.type!=null ?
+ this.type.resolveType(scope, true /* check bounds*/) : javaLangError;
+ if (exceptionType == null) return null;
+ boolean hasError = false;
+
+ Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
+ if (existingVariable != null && existingVariable.isValidBinding()){
+// if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+// scope.problemReporter().redefineArgument(this);
+// } else {
+ scope.problemReporter().localVariableHiding(this, existingVariable, false);
+// }
+ }
+
+ this.binding = new LocalVariableBinding(this, exceptionType, modifiers, false); // argument decl, but local var (where isArgument = false)
+// resolveAnnotations(scope, this.annotations, this.binding);
+
+ scope.addLocalVariable(binding);
+ if (hasError) return null;
+ return exceptionType;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (type != null)
+ type.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (type != null)
+ type.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+
+ public int getASTType() {
+ return IASTNode.ARGUMENT;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayAllocationExpression.java
new file mode 100644
index 0000000..f1ab061
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IArrayAllocationExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class ArrayAllocationExpression extends Expression implements IArrayAllocationExpression {
+
+ public TypeReference type;
+
+ //dimensions.length gives the number of dimensions, but the
+ // last ones may be nulled as in new int[4][5][][]
+ public Expression[] dimensions;
+ public ArrayInitializer initializer;
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ for (int i = 0, max = this.dimensions.length; i < max; i++) {
+ Expression dim;
+ if ((dim = this.dimensions[i]) != null) {
+ flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
+ }
+ }
+ if (this.initializer != null) {
+ return this.initializer.analyseCode(currentScope, flowContext, flowInfo);
+ }
+ return flowInfo;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append("new "); //$NON-NLS-1$
+ this.type.print(0, output);
+ for (int i = 0; i < this.dimensions.length; i++) {
+ if (this.dimensions[i] == null)
+ output.append("[]"); //$NON-NLS-1$
+ else {
+ output.append('[');
+ this.dimensions[i].printExpression(0, output);
+ output.append(']');
+ }
+ }
+ if (this.initializer != null) this.initializer.printExpression(0, output);
+ return output;
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ // Build an array type reference using the current dimensions
+ // The parser does not check for the fact that dimension may be null
+ // only at the -end- like new int [4][][]. The parser allows new int[][4][]
+ // so this must be checked here......(this comes from a reduction to LL1 grammar)
+
+ TypeBinding referenceType = this.type.resolveType(scope, true /* check bounds*/);
+
+ // will check for null after dimensions are checked
+ this.constant = Constant.NotAConstant;
+
+ // check the validity of the dimension syntax (and test for all null dimensions)
+ int explicitDimIndex = -1;
+ loop: for (int i = this.dimensions.length; --i >= 0;) {
+ if (this.dimensions[i] != null) {
+ if (explicitDimIndex < 0) explicitDimIndex = i;
+ } else if (explicitDimIndex > 0) {
+ break loop;
+ }
+ }
+
+ // dimensions resolution
+ for (int i = 0; i <= explicitDimIndex; i++) {
+ Expression dimExpression;
+ if ((dimExpression = this.dimensions[i]) != null) {
+ TypeBinding dimensionType = dimExpression.resolveTypeExpecting(scope, TypeBinding.INT);
+ }
+ }
+
+ // building the array binding
+ if (referenceType != null) {
+ this.resolvedType = scope.createArrayType(referenceType, this.dimensions.length);
+
+ // check the initializer
+ if (this.initializer != null) {
+ if ((this.initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
+ this.initializer.binding = (ArrayBinding)this.resolvedType;
+ }
+ }
+ return this.resolvedType;
+ }
+
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ int dimensionsLength = this.dimensions.length;
+ this.type.traverse(visitor, scope);
+ for (int i = 0; i < dimensionsLength; i++) {
+ if (this.dimensions[i] != null)
+ this.dimensions[i].traverse(visitor, scope);
+ }
+ if (this.initializer != null)
+ this.initializer.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.ARRAY_ALLOCATION_EXPRESSION;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayInitializer.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayInitializer.java
new file mode 100644
index 0000000..7b5f95f
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayInitializer.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IArrayInitializer;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class ArrayInitializer extends Expression implements IArrayInitializer {
+
+ public Expression[] expressions;
+ public ArrayBinding binding; //the type of the { , , , }
+
+ /**
+ * ArrayInitializer constructor comment.
+ */
+ public ArrayInitializer() {
+
+ super();
+ }
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ if (expressions != null) {
+ for (int i = 0, max = expressions.length; i < max; i++) {
+ flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ }
+ }
+ return flowInfo;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ output.append('[');
+ if (expressions != null) {
+ int j = 20 ;
+ for (int i = 0 ; i < expressions.length ; i++) {
+ if (i > 0) output.append(", "); //$NON-NLS-1$
+ if (expressions[i]!=null)
+ expressions[i].printExpression(0, output);
+ j -- ;
+ if (j == 0) {
+ output.append('\n');
+ printIndent(indent+1, output);
+ j = 20;
+ }
+ }
+ }
+ return output.append(']');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ this.constant = Constant.NotAConstant;
+ this.resolvedType = this.binding = new ArrayBinding(TypeBinding.UNKNOWN,1,scope.environment());
+ if (this.expressions!=null)
+ for (int i = 0, length = this.expressions.length; i < length; i++) {
+ Expression expression = this.expressions[i];
+ expression.resolveType(scope);
+ }
+ return this.resolvedType;
+ }
+
+ public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedType) {
+ // Array initializers can only occur on the right hand side of an assignment
+ // expression, therefore the expected type contains the valid information
+ // concerning the type that must be enforced by the elements of the array initializer.
+
+ // this method is recursive... (the test on isArrayType is the stop case)
+
+ this.constant = Constant.NotAConstant;
+
+ if (expectedType instanceof ArrayBinding) {
+ // allow new List>[5]
+ if ((this.bits & IsAnnotationDefaultValue) == 0) { // annotation default value need only to be commensurate JLS9.7
+ // allow new List>[5] - only check for generic array when no initializer, since also checked inside initializer resolution
+ }
+ this.resolvedType = this.binding = (ArrayBinding) expectedType;
+ if (this.expressions == null)
+ return this.binding;
+ TypeBinding elementType = this.binding.elementsType();
+ for (int i = 0, length = this.expressions.length; i < length; i++) {
+ Expression expression = this.expressions[i];
+ expression.setExpectedType(elementType);
+ TypeBinding exprType = expression instanceof ArrayInitializer
+ ? expression.resolveTypeExpecting(scope, elementType)
+ : expression.resolveType(scope);
+ if (exprType == null)
+ continue;
+
+ // Compile-time conversion required?
+ if (elementType != exprType) // must call before computeConversion() and typeMismatchError()
+ scope.compilationUnitScope().recordTypeConversion(elementType, exprType);
+
+ if ((expression.isConstantValueOfTypeAssignableToType(exprType, elementType)
+ || (elementType.isBaseType() && BaseTypeBinding.isWidening(elementType.id, exprType.id)))
+ || exprType.isCompatibleWith(elementType)) {
+ } else if (scope.isBoxingCompatibleWith(exprType, elementType)
+ || (exprType.isBaseType() // narrowing then boxing ?
+ && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
+ && !elementType.isBaseType()
+ && expression.isConstantValueOfTypeAssignableToType(exprType, scope.environment().computeBoxingType(elementType)))) {
+ } else {
+ scope.problemReporter().typeMismatchError(exprType, elementType, expression);
+// return null;
+ }
+ }
+ return this.binding;
+ }
+
+ // infer initializer type for error reporting based on first element
+ TypeBinding leafElementType = null;
+ int dim = 1;
+ if (this.expressions == null) {
+ leafElementType = TypeBinding.UNKNOWN;
+ } else {
+ Expression expression = this.expressions[0];
+ while(expression != null && expression instanceof ArrayInitializer) {
+ dim++;
+ Expression[] subExprs = ((ArrayInitializer) expression).expressions;
+ if (subExprs == null){
+ leafElementType = scope.getJavaLangObject();
+ expression = null;
+ break;
+ }
+ expression = ((ArrayInitializer) expression).expressions[0];
+ }
+ if (expression != null) {
+ leafElementType = expression.resolveType(scope);
+ }
+ // fault-tolerance - resolve other expressions as well
+ for (int i = 1, length = this.expressions.length; i < length; i++) {
+ expression = this.expressions[i];
+ if (expression != null) {
+ expression.resolveType(scope) ;
+ }
+ } }
+ if (leafElementType != null) {
+ this.resolvedType = scope.createArrayType(leafElementType, dim);
+ if (expectedType != null )
+ scope.problemReporter().typeMismatchError(this.resolvedType, expectedType, this);
+ }
+ return null;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (this.expressions != null) {
+ int expressionsLength = this.expressions.length;
+ for (int i = 0; i < expressionsLength; i++)
+ if (this.expressions[i]!=null)
+ this.expressions[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.ARRAY_INITIALIZER;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
new file mode 100644
index 0000000..82ec908
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IArrayQualifiedTypeReference;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilation;
+
+public class ArrayQualifiedTypeReference extends QualifiedTypeReference implements IArrayQualifiedTypeReference {
+ int dimensions;
+
+ public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
+
+ super( sources , poss);
+ dimensions = dim ;
+ }
+
+ public int dimensions() {
+
+ return dimensions;
+ }
+
+ /**
+ * @return char[][]
+ */
+ public char [][] getParameterizedTypeName(){
+ int dim = this.dimensions;
+ char[] dimChars = new char[dim*2];
+ for (int i = 0; i < dim; i++) {
+ int index = i*2;
+ dimChars[index] = '[';
+ dimChars[index+1] = ']';
+ }
+ int length = this.tokens.length;
+ char[][] qParamName = new char[length][];
+ System.arraycopy(this.tokens, 0, qParamName, 0, length-1);
+ qParamName[length-1] = CharOperation.concat(this.tokens[length-1], dimChars);
+ return qParamName;
+ }
+
+ protected TypeBinding getTypeBinding(Scope scope) {
+
+ if (this.resolvedType != null)
+ return this.resolvedType;
+ LookupEnvironment env = scope.environment();
+ try {
+ env.missingClassFileLocation = this;
+ TypeBinding leafComponentType = super.getTypeBinding(scope);
+ return this.resolvedType = scope.createArrayType(leafComponentType, dimensions);
+ } catch (AbortCompilation e) {
+ e.updateContext(this, scope.referenceCompilationUnit().compilationResult);
+ throw e;
+ } finally {
+ env.missingClassFileLocation = null;
+ }
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output){
+
+ super.printExpression(indent, output);
+ if ((this.bits & IsVarArgs) != 0) {
+ for (int i= 0 ; i < dimensions - 1; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ output.append("..."); //$NON-NLS-1$
+ } else {
+ for (int i= 0 ; i < dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ }
+ return output;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.ARRAY_QUALIFIED_TYPE_REFERENCE;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayReference.java
new file mode 100644
index 0000000..fb55d92
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayReference.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IArrayReference;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class ArrayReference extends Reference implements IArrayReference {
+
+ public Expression receiver;
+ public Expression position;
+
+ public ArrayReference(Expression rec, Expression pos) {
+ this.receiver = rec;
+ this.position = pos;
+ sourceStart = rec.sourceStart;
+ }
+
+public FlowInfo analyseAssignment(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo,
+ Assignment assignment,
+ boolean compoundAssignment) {
+ // TODO (maxime) optimization: unconditionalInits is applied to all existing calls
+ if (assignment.expression == null) {
+ return analyseCode(currentScope, flowContext, flowInfo);
+ }
+ return assignment
+ .expression
+ .analyseCode(
+ currentScope,
+ flowContext,
+ analyseCode(currentScope, flowContext, flowInfo).unconditionalInits());
+}
+
+public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+ receiver.checkNPE(currentScope, flowContext, flowInfo);
+ flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
+ return position.analyseCode(currentScope, flowContext, flowInfo);
+}
+
+ public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.UNKNOWN;
+}
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ receiver.printExpression(0, output).append('[');
+ return position.printExpression(0, output).append(']');
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ constant = Constant.NotAConstant;
+// if (receiver instanceof CastExpression // no cast check for ((type[])null)[0]
+// && ((CastExpression)receiver).innermostCastedExpression() instanceof NullLiteral) {
+// this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
+// }
+ TypeBinding arrayType = receiver.resolveType(scope);
+ if (arrayType != null) {
+ if (arrayType.isArrayType()) {
+ TypeBinding elementType = ((ArrayBinding) arrayType).elementsType();
+ this.resolvedType = elementType;
+ } else if (arrayType instanceof SourceTypeBinding) {
+ this.resolvedType = TypeBinding.UNKNOWN;
+ FieldBinding[] fields = ((SourceTypeBinding) arrayType).fields();
+ if (position instanceof StringLiteral) {
+ char[] positionSource = ((StringLiteral) position).source;
+ for (int idx = 0; idx < fields.length; idx++) {
+ if (CharOperation.equals(positionSource, fields[idx].name)) {
+ this.resolvedType = fields[idx].type;
+ break;
+ }
+ }
+ }
+ } else {
+// scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
+ this.resolvedType=TypeBinding.UNKNOWN;
+ }
+ }
+ else
+ this.resolvedType=TypeBinding.UNKNOWN;
+ position.resolveTypeExpecting(scope, new TypeBinding[] {scope.getJavaLangNumber(),scope.getJavaLangString(),TypeBinding.ANY});
+// if (positionType != null) {
+// position.computeConversion(scope, TypeBinding.INT, positionType);
+// }
+ return this.resolvedType;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ receiver.traverse(visitor, scope);
+ position.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.ARRAY_REFERENCE;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayTypeReference.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayTypeReference.java
new file mode 100644
index 0000000..55e173c
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ArrayTypeReference.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IArrayTypeReference;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class ArrayTypeReference extends SingleTypeReference implements IArrayTypeReference {
+ public int dimensions;
+ public int originalSourceEnd;
+
+ /**
+ * ArrayTypeReference constructor comment.
+ * @param source char[]
+ * @param dimensions int
+ * @param pos int
+ */
+ public ArrayTypeReference(char[] source, int dimensions, long pos) {
+
+ super(source, pos);
+ this.originalSourceEnd = this.sourceEnd;
+ this.dimensions = dimensions ;
+ }
+
+ public int dimensions() {
+
+ return dimensions;
+ }
+ /**
+ * @return char[][]
+ */
+ public char [][] getParameterizedTypeName(){
+ int dim = this.dimensions;
+ char[] dimChars = new char[dim*2];
+ for (int i = 0; i < dim; i++) {
+ int index = i*2;
+ dimChars[index] = '[';
+ dimChars[index+1] = ']';
+ }
+ return new char[][]{ CharOperation.concat(token, dimChars) };
+ }
+ protected TypeBinding getTypeBinding(Scope scope) {
+
+ if (this.resolvedType != null) return this.resolvedType;
+ TypeBinding leafComponentType = scope.getType(token);
+ return scope.createArrayType(leafComponentType, dimensions);
+
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output){
+
+ super.printExpression(indent, output);
+ if ((this.bits & IsVarArgs) != 0) {
+ for (int i= 0 ; i < dimensions - 1; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ output.append("..."); //$NON-NLS-1$
+ } else {
+ for (int i= 0 ; i < dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ }
+ return output;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+ public int getASTType() {
+ return IASTNode.ARRAY_TYPE_REFERENCE;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Assignment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Assignment.java
new file mode 100644
index 0000000..97942cf
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Assignment.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Genady Beriozkin - added support for reporting assignment with no effect
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IAssignment;
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.core.ast.IJsDoc;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TagBits;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class Assignment extends Expression implements IAssignment {
+
+ public Expression lhs;
+ public Expression expression;
+ public Javadoc javadoc;
+ public InferredType inferredType;
+
+public Assignment(Expression lhs, Expression expression, int sourceEnd) {
+ //lhs is always a reference by construction ,
+ //but is build as an expression ==> the checkcast cannot fail
+ this.lhs = lhs;
+ lhs.bits |= IsStrictlyAssigned; // tag lhs as assigned
+ this.expression = expression;
+ this.sourceStart = lhs.sourceStart;
+ this.sourceEnd = sourceEnd;
+}
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ // record setting a variable: various scenarii are possible, setting an array reference,
+// a field reference, a blank final field reference, a field of an enclosing instance or
+// just a local variable.
+ LocalVariableBinding local = this.lhs.localVariableBinding();
+// if (local!=null && local.isSameCompilationUnit(currentScope))
+// local=null;
+ int nullStatus = this.expression.nullStatus(flowInfo);
+ if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
+ if (nullStatus == FlowInfo.NULL) {
+ flowContext.recordUsingNullReference(currentScope, local, this.lhs,
+ FlowContext.CAN_ONLY_NULL| FlowContext.IN_ASSIGNMENT, flowInfo);
+ }
+ }
+ flowInfo = ((Reference) lhs)
+ .analyseAssignment(currentScope, flowContext, flowInfo, this, false)
+ .unconditionalInits();
+ if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
+ switch(nullStatus) {
+ case FlowInfo.NULL :
+ flowInfo.markAsDefinitelyNull(local);
+ break;
+ case FlowInfo.NON_NULL :
+ flowInfo.markAsDefinitelyNonNull(local);
+ break;
+ default:
+ flowInfo.markAsDefinitelyUnknown(local);
+ }
+ if (flowContext.initsOnFinally != null) {
+ switch(nullStatus) {
+ case FlowInfo.NULL :
+ flowContext.initsOnFinally.markAsDefinitelyNull(local);
+ break;
+ case FlowInfo.NON_NULL :
+ flowContext.initsOnFinally.markAsDefinitelyNonNull(local);
+ break;
+ default:
+ flowContext.initsOnFinally.markAsDefinitelyUnknown(local);
+ }
+ }
+ }
+ return flowInfo;
+}
+
+void checkAssignment(BlockScope scope, TypeBinding lhsType, TypeBinding rhsType) {
+// FieldBinding leftField = getLastField(this.lhs);
+// if (leftField != null && !leftField.isStatic() && leftField.declaringClass != null /*length pseudo field*/&& leftField.declaringClass.isRawType()) {
+// scope.problemReporter().unsafeRawFieldAssignment(leftField, rhsType, this.lhs);
+// } else
+}
+
+public static Binding getDirectBinding(Expression someExpression) {
+ if ((someExpression.bits & ASTNode.IgnoreNoEffectAssignCheck) != 0) {
+ return null;
+ }
+ if (someExpression instanceof SingleNameReference) {
+ return ((SingleNameReference)someExpression).binding;
+ } else if (someExpression instanceof FieldReference) {
+ FieldReference fieldRef = (FieldReference)someExpression;
+ if (fieldRef.receiver.isThis() && !(fieldRef.receiver instanceof QualifiedThisReference)) {
+ return fieldRef.binding;
+ }
+ } else if (someExpression instanceof Assignment) {
+ Expression lhs = ((Assignment)someExpression).lhs;
+ if ((lhs.bits & ASTNode.IsStrictlyAssigned) != 0) {
+ // i = i = ...; // eq to int i = ...;
+ return getDirectBinding (((Assignment)someExpression).lhs);
+ } else if (someExpression instanceof PrefixExpression) {
+ // i = i++; // eq to ++i;
+ return getDirectBinding (((Assignment)someExpression).lhs);
+ }
+ }
+// } else if (someExpression instanceof PostfixExpression) { // recurse for postfix: i++ --> i
+// // note: "b = b++" is equivalent to doing nothing, not to "b++"
+// return getDirectBinding(((PostfixExpression) someExpression).lhs);
+ return null;
+}
+
+
+
+public int nullStatus(FlowInfo flowInfo) {
+ return this.expression.nullStatus(flowInfo);
+}
+
+public StringBuffer print(int indent, StringBuffer output) {
+ //no () when used as a statement
+ printIndent(indent, output);
+ return printExpressionNoParenthesis(indent, output);
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+ //subclass redefine printExpressionNoParenthesis()
+ output.append('(');
+ return printExpressionNoParenthesis(0, output).append(')');
+}
+
+public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+ lhs.printExpression(indent, output).append(" = "); //$NON-NLS-1$
+ return expression.printExpression(0, output);
+}
+
+public StringBuffer printStatement(int indent, StringBuffer output) {
+ //no () when used as a statement
+ return print(indent, output).append(';');
+}
+
+public TypeBinding resolveType(BlockScope scope) {
+ // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
+ this.constant = Constant.NotAConstant;
+ if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
+ scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+ return null;
+ }
+ TypeBinding rhsType = this.expression.resolveType(scope);
+ TypeBinding lhsType = lhs.resolveType(scope,true,rhsType);
+// this.expression.setExpectedType(lhsType); // needed in case of generic method invocation
+ if (lhsType != null)
+ this.resolvedType = lhsType;
+ if (lhsType == null || rhsType == null) {
+ return null;
+ }
+
+ //check if the lhs is prototype, in which case we are done
+ if( lhs instanceof FieldReference && ((FieldReference)lhs).isPrototype() )
+ return this.resolvedType;
+
+ // check for assignment with no effect
+ Binding left = getDirectBinding(this.lhs);
+ if (left != null && left == getDirectBinding(this.expression)) {
+ scope.problemReporter().assignmentHasNoEffect(this, left.shortReadableName());
+ }
+
+ // Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
+ // may require to widen the rhs expression at runtime
+// if (lhsType != rhsType) // must call before computeConversion() and typeMismatchError()
+// scope.compilationUnitScope().recordTypeConversion(lhsType, rhsType);
+
+
+ if ((this.expression.isConstantValueOfTypeAssignableToType(rhsType, lhsType)
+ || (lhsType.isBaseType() && BaseTypeBinding.isWidening(lhsType.id, rhsType.id)))
+ || rhsType.isCompatibleWith(lhsType)) {
+// this.expression.computeConversion(scope, lhsType, rhsType);
+ checkAssignment(scope, lhsType, rhsType);
+ return this.resolvedType;
+ } else if (scope.isBoxingCompatibleWith(rhsType, lhsType)
+ || (rhsType.isBaseType() // narrowing then boxing ?
+ && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
+ && !lhsType.isBaseType()
+ && this.expression.isConstantValueOfTypeAssignableToType(rhsType, scope.environment().computeBoxingType(lhsType)))) {
+ return this.resolvedType;
+ }
+ if (rhsType.isFunctionType() && this.lhs.isTypeReference())
+ return lhsType;
+ //scope.problemReporter().typeMismatchError(rhsType, lhsType, this.expression);
+ return lhsType;
+}
+
+/**
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#resolveTypeExpecting(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding)
+ */
+public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedType) {
+
+ TypeBinding type = super.resolveTypeExpecting(scope, expectedType);
+ if (type == null) return null;
+ TypeBinding lhsType = this.resolvedType;
+ TypeBinding rhsType = this.expression.resolvedType;
+ // signal possible accidental boolean assignment (instead of using '==' operator)
+ if (expectedType == TypeBinding.BOOLEAN
+ && lhsType == TypeBinding.BOOLEAN
+ && (this.lhs.bits & IsStrictlyAssigned) != 0) {
+ scope.problemReporter().possibleAccidentalBooleanAssignment(this);
+ }
+ checkAssignment(scope, lhsType, rhsType);
+ return type;
+}
+
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ lhs.traverse(visitor, scope);
+ expression.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+}
+public LocalVariableBinding localVariableBinding() {
+ return lhs.localVariableBinding();
+}
+public int getASTType() {
+ return IASTNode.ASSIGNMENT;
+
+}
+
+public IExpression getExpression() {
+ return this.expression;
+}
+
+public IExpression getLeftHandSide() {
+ return this.lhs;
+}
+
+public IJsDoc getJsDoc() {
+ return javadoc;
+}
+
+public void setInferredType(InferredType type) {
+ this.inferredType = type;
+
+}
+
+public InferredType getInferredType() {
+ return this.inferredType;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BinaryExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BinaryExpression.java
new file mode 100644
index 0000000..8e0c81e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BinaryExpression.java
@@ -0,0 +1,383 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IBinaryExpression;
+import org.eclipse.wst.jsdt.core.ast.IExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeIds;
+
+public class BinaryExpression extends OperatorExpression implements IBinaryExpression {
+
+/* Tracking helpers
+ * The following are used to elaborate realistic statistics about binary
+ * expressions. This must be neutralized in the released code.
+ * Search the keyword BE_INSTRUMENTATION to reenable.
+ * An external device must install a suitable probe so as to monitor the
+ * emission of events and publish the results.
+ public interface Probe {
+ public void ping(int depth);
+ }
+ public int depthTracker;
+ public static Probe probe;
+ */
+
+ public Expression left, right;
+ public Constant optimizedBooleanConstant;
+
+public BinaryExpression(Expression left, Expression right, int operator) {
+ this.left = left;
+ this.right = right;
+ this.bits |= operator << ASTNode.OperatorSHIFT; // encode operator
+ this.sourceStart = left.sourceStart;
+ this.sourceEnd = right.sourceEnd;
+ // BE_INSTRUMENTATION: neutralized in the released code
+// if (left instanceof BinaryExpression &&
+// ((left.bits & OperatorMASK) ^ (this.bits & OperatorMASK)) == 0) {
+// this.depthTracker = ((BinaryExpression)left).depthTracker + 1;
+// } else {
+// this.depthTracker = 1;
+// }
+}
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
+ FlowInfo flowInfo) {
+ // keep implementation in sync with CombinedBinaryExpression#analyseCode
+ if (this.resolvedType.id == TypeIds.T_JavaLangString) {
+ return this.right.analyseCode(
+ currentScope, flowContext,
+ this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
+ .unconditionalInits();
+ } else {
+ this.left.checkNPE(currentScope, flowContext, flowInfo);
+ flowInfo = this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ this.right.checkNPE(currentScope, flowContext, flowInfo);
+ return this.right.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ }
+}
+
+public void computeConstant(BlockScope scope, int leftId, int rightId) {
+ //compute the constant when valid
+
+ /* bchilds - Not sure about this change but left side was null (variable) and causing NPE further down */
+
+ if(this.left.constant==null) this.left.constant= Constant.NotAConstant;
+ if(this.right.constant==null) this.left.constant= Constant.NotAConstant;
+
+ if ((this.left.constant != Constant.NotAConstant)
+ && (this.right.constant != Constant.NotAConstant)) {
+ try {
+ this.constant =
+ Constant.computeConstantOperation(
+ this.left.constant,
+ leftId,
+ (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT,
+ this.right.constant,
+ rightId);
+ } catch (Exception e) {
+ this.constant = Constant.NotAConstant;
+ // 1.2 no longer throws an exception at compile-time
+ //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
+ }
+ } else {
+ this.constant = Constant.NotAConstant;
+ //add some work for the boolean operators & |
+ this.optimizedBooleanConstant(
+ leftId,
+ (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT,
+ rightId);
+ }
+}
+
+public Constant optimizedBooleanConstant() {
+ return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant;
+}
+
+public boolean isCompactableOperation() {
+ return true;
+}
+
+/**
+ * Separates into a reusable method the subpart of {@link
+ * #resolveType(BlockScope)} that needs to be executed while climbing up the
+ * chain of expressions of this' leftmost branch. For use by {@link
+ * CombinedBinaryExpression#resolveType(BlockScope)}.
+ * @param scope the scope within which the resolution occurs
+ */
+void nonRecursiveResolveTypeUpwards(BlockScope scope) {
+ // keep implementation in sync with BinaryExpression#resolveType
+ TypeBinding leftType = this.left.resolvedType;
+
+ TypeBinding rightType = this.right.resolveType(scope);
+
+ // use the id of the type to navigate into the table
+ if (leftType == null || rightType == null) {
+ this.constant = Constant.NotAConstant;
+ return;
+ }
+
+ int leftTypeID = leftType.id;
+ int rightTypeID = rightType.id;
+
+ // autoboxing support
+ boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
+ if (use15specifics) {
+ if (!leftType.isBaseType() && rightTypeID != TypeIds.T_JavaLangString && rightTypeID != TypeIds.T_null) {
+ leftTypeID = scope.environment().computeBoxingType(leftType).id;
+ }
+ if (!rightType.isBaseType() && leftTypeID != TypeIds.T_JavaLangString && leftTypeID != TypeIds.T_null) {
+ rightTypeID = scope.environment().computeBoxingType(rightType).id;
+ }
+ }
+ if (leftTypeID > 15
+ || rightTypeID > 15) { // must convert String + Object || Object + String
+ if (leftTypeID == TypeIds.T_JavaLangString) {
+ rightTypeID = TypeIds.T_JavaLangObject;
+ } else if (rightTypeID == TypeIds.T_JavaLangString) {
+ leftTypeID = TypeIds.T_JavaLangObject;
+ } else {
+ this.constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftType, rightType);
+ return;
+ }
+ }
+
+ // the code is an int
+ // (cast) left Op (cast) right --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+
+ // Don't test for result = 0. If it is zero, some more work is done.
+ // On the one hand when it is not zero (correct code) we avoid doing the test
+ int operator = (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
+ int operatorSignature = OperatorExpression.OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID];
+
+ this.bits |= operatorSignature & 0xF;
+ switch (operatorSignature & 0xF) { // record the current ReturnTypeID
+ // only switch on possible result type.....
+ case T_boolean :
+ this.resolvedType = TypeBinding.BOOLEAN;
+ break;
+ case T_char :
+ this.resolvedType = TypeBinding.CHAR;
+ break;
+ case T_double :
+ this.resolvedType = TypeBinding.DOUBLE;
+ break;
+ case T_float :
+ this.resolvedType = TypeBinding.FLOAT;
+ break;
+ case T_int :
+ this.resolvedType = TypeBinding.INT;
+ break;
+ case T_long :
+ this.resolvedType = TypeBinding.LONG;
+ break;
+ case T_JavaLangString :
+ this.resolvedType = scope.getJavaLangString();
+ break;
+ default : //error........
+ this.constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftType, rightType);
+ return;
+ }
+
+ // compute the constant when valid
+ computeConstant(scope, leftTypeID, rightTypeID);
+}
+
+public void optimizedBooleanConstant(int leftId, int operator, int rightId) {
+ switch (operator) {
+ case AND :
+ if ((leftId != TypeIds.T_boolean) || (rightId != TypeIds.T_boolean))
+ return;
+ case AND_AND :
+ Constant cst;
+ if ((cst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) {
+ if (cst.booleanValue() == false) { // left is equivalent to false
+ this.optimizedBooleanConstant = cst; // constant(false)
+ return;
+ } else { //left is equivalent to true
+ if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+ this.optimizedBooleanConstant = cst;
+ // the conditional result is equivalent to the right conditional value
+ }
+ return;
+ }
+ }
+ if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+ if (cst.booleanValue() == false) { // right is equivalent to false
+ this.optimizedBooleanConstant = cst; // constant(false)
+ }
+ }
+ return;
+ case OR :
+ if ((leftId != TypeIds.T_boolean) || (rightId != TypeIds.T_boolean))
+ return;
+ case OR_OR :
+ if ((cst = this.left.optimizedBooleanConstant()) != Constant.NotAConstant) {
+ if (cst.booleanValue() == true) { // left is equivalent to true
+ this.optimizedBooleanConstant = cst; // constant(true)
+ return;
+ } else { //left is equivalent to false
+ if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+ this.optimizedBooleanConstant = cst;
+ }
+ return;
+ }
+ }
+ if ((cst = this.right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+ if (cst.booleanValue() == true) { // right is equivalent to true
+ this.optimizedBooleanConstant = cst; // constant(true)
+ }
+ }
+ }
+}
+
+public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+ // keep implementation in sync with
+ // CombinedBinaryExpression#printExpressionNoParenthesis
+ this.left.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
+ return this.right.printExpression(0, output);
+}
+
+public TypeBinding resolveType(BlockScope scope) {
+ // keep implementation in sync with CombinedBinaryExpression#resolveType
+ // and nonRecursiveResolveTypeUpwards
+ TypeBinding leftType = this.left.resolveType(scope);
+ TypeBinding rightType = this.right.resolveType(scope);
+
+ // use the id of the type to navigate into the table
+ if (leftType == null || rightType == null) {
+ this.constant = Constant.NotAConstant;
+ this.resolvedType=TypeBinding.ANY;
+ return null;
+ }
+ int operator = (this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
+
+ int leftTypeID = leftType.id;
+ int rightTypeID = rightType.id;
+
+ if(operator==OperatorIds.INSTANCEOF || operator==OperatorIds.IN || operator==OperatorIds.OR_OR) {
+ if ( rightTypeID>15)
+ rightTypeID= TypeIds.T_JavaLangObject;
+ if ( leftTypeID>15)
+ leftTypeID= TypeIds.T_JavaLangObject;
+ }
+
+ // autoboxing support
+ boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
+ if (use15specifics) {
+ if (!leftType.isBaseType() && rightTypeID != TypeIds.T_JavaLangString && rightTypeID != TypeIds.T_null) {
+ leftTypeID = scope.environment().computeBoxingType(leftType).id;
+ }
+ if (!rightType.isBaseType() && leftTypeID != TypeIds.T_JavaLangString && leftTypeID != TypeIds.T_null) {
+ rightTypeID = scope.environment().computeBoxingType(rightType).id;
+ }
+ }
+ if (rightType.isArrayType())
+ {
+ rightType=rightType.leafComponentType();
+ rightTypeID=rightType.id;
+ }
+ if (leftTypeID > 15
+ || rightTypeID > 15) { // must convert String + Object || Object + String
+
+ if (leftTypeID == TypeIds.T_JavaLangString) {
+ rightTypeID = TypeIds.T_JavaLangObject;
+ } else if (rightTypeID == TypeIds.T_JavaLangString) {
+ leftTypeID = TypeIds.T_JavaLangObject;
+ } else {
+
+ this.constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftType, rightType);
+ return null;
+ }
+ }
+
+ // the code is an int
+ // (cast) left Op (cast) right --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+
+ // Don't test for result = 0. If it is zero, some more work is done.
+ // On the one hand when it is not zero (correct code) we avoid doing the test
+ int operatorSignature = OperatorExpression.OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID];
+
+ this.bits |= operatorSignature & 0xF;
+ switch (operatorSignature & 0xF) { // record the current ReturnTypeID
+ // only switch on possible result type.....
+ case T_boolean :
+ this.resolvedType = TypeBinding.BOOLEAN;
+ break;
+ case T_char :
+ this.resolvedType = TypeBinding.CHAR;
+ break;
+ case T_double :
+ this.resolvedType = TypeBinding.DOUBLE;
+ break;
+ case T_float :
+ this.resolvedType = TypeBinding.FLOAT;
+ break;
+ case T_int :
+ this.resolvedType = scope.getJavaLangNumber();
+ break;
+ case T_long :
+ this.resolvedType = TypeBinding.LONG;
+ break;
+ case T_JavaLangString :
+ this.resolvedType = scope.getJavaLangString();
+ break;
+ case T_any:
+ this.resolvedType = TypeBinding.UNKNOWN;
+ break;
+ case T_function:
+ this.resolvedType = scope.getJavaLangFunction();
+ break;
+ case T_JavaLangObject:
+ this.resolvedType = scope.getJavaLangObject();
+ break;
+ default : //error........
+ this.constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftType, rightType);
+ return null;
+ }
+
+ // compute the constant when valid
+ computeConstant(scope, leftTypeID, rightTypeID);
+ return this.resolvedType;
+}
+
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ this.left.traverse(visitor, scope);
+ this.right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+}
+public int getASTType() {
+ return IASTNode.BINARY_EXPRESSION;
+
+}
+public IExpression getLeft() {
+ return left;
+}
+public IExpression getRight() {
+ return right;
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Block.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Block.java
new file mode 100644
index 0000000..29f68b4
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Block.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.JavaScriptCore;
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IBlock;
+import org.eclipse.wst.jsdt.core.ast.IStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+public class Block extends Statement implements IBlock {
+
+ public Statement[] statements;
+ public int explicitDeclarations;
+ // the number of explicit declaration , used to create scope
+ public BlockScope scope;
+
+ public Block(int explicitDeclarations) {
+ this.explicitDeclarations = explicitDeclarations;
+ }
+
+ public IStatement[] getStatements() {
+ return statements;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ // empty block
+ if (statements == null) return flowInfo;
+ boolean didAlreadyComplain = false;
+ for (int i = 0, max = statements.length; i < max; i++) {
+ Statement stat = statements[i];
+ if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
+ flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
+ } else {
+ didAlreadyComplain = true;
+ }
+ }
+ return flowInfo;
+ }
+ public boolean isEmptyBlock() {
+
+ return statements == null;
+ }
+
+ public StringBuffer printBody(int indent, StringBuffer output) {
+
+ if (this.statements == null) return output;
+ for (int i = 0; i < statements.length; i++) {
+ statements[i].printStatement(indent + 1, output);
+ output.append('\n');
+ }
+ return output;
+ }
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+
+ printIndent(indent, output);
+ output.append("{\n"); //$NON-NLS-1$
+ printBody(indent, output);
+ return printIndent(indent, output).append('}');
+ }
+
+ public void resolve(BlockScope upperScope) {
+
+ if ((this.bits & UndocumentedEmptyBlock) != 0) {
+ upperScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd);
+ }
+ if (statements != null) {
+ scope =
+ (!JavaScriptCore.IS_ECMASCRIPT4 || explicitDeclarations == 0)
+ ? upperScope
+ : new BlockScope(upperScope, explicitDeclarations);
+ for (int i = 0, length = statements.length; i < length; i++) {
+ statements[i].resolve(scope);
+ }
+ }
+ }
+
+ public void resolveUsing(BlockScope givenScope) {
+
+ if ((this.bits & UndocumentedEmptyBlock) != 0) {
+ givenScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd);
+ }
+ // this optimized resolve(...) is sent only on none empty blocks
+ scope = givenScope;
+ if (statements != null) {
+ for (int i = 0, length = statements.length; i < length; i++) {
+ statements[i].resolve(scope);
+ }
+ }
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ BlockScope blockScope) {
+
+ BlockScope visitScope=(scope!=null) ? scope:blockScope;
+ if (visitor.visit(this, blockScope)) {
+ if (statements != null) {
+ for (int i = 0, length = statements.length; i < length; i++)
+ statements[i].traverse(visitor, visitScope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+ }
+ public int getASTType() {
+ return IASTNode.BLOCK;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BranchStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BranchStatement.java
new file mode 100644
index 0000000..48279ef
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BranchStatement.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IBranchStatement;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+public abstract class BranchStatement extends Statement implements IBranchStatement {
+
+ public char[] label;
+ public SubRoutineStatement[] subroutines;
+ public int initStateIndex = -1;
+
+/**
+ * BranchStatement constructor comment.
+ */
+public BranchStatement(char[] label, int sourceStart,int sourceEnd) {
+ this.label = label ;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+}
+
+public void resolve(BlockScope scope) {
+ // nothing to do during name resolution
+}
+public int getASTType() {
+ return IASTNode.BRANCH_STATEMENT;
+
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BreakStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BreakStatement.java
new file mode 100644
index 0000000..d3f462b
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/BreakStatement.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IBreakStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.flow.InsideSubRoutineFlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+
+public class BreakStatement extends BranchStatement implements IBreakStatement {
+
+public BreakStatement(char[] label, int sourceStart, int e) {
+ super(label, sourceStart, e);
+}
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ // here requires to generate a sequence of finally blocks invocations depending corresponding
+ // to each of the traversed try statements, so that execution will terminate properly.
+
+ // lookup the label, this should answer the returnContext
+ FlowContext targetContext = (this.label == null)
+ ? flowContext.getTargetContextForDefaultBreak()
+ : flowContext.getTargetContextForBreakLabel(this.label);
+
+ if (targetContext == null) {
+ if (this.label == null) {
+ currentScope.problemReporter().invalidBreak(this);
+ } else {
+ currentScope.problemReporter().undefinedLabel(this);
+ }
+ return flowInfo; // pretend it did not break since no actual target
+ }
+
+// this.initStateIndex =
+// currentScope.methodScope().recordInitializationStates(flowInfo);
+//
+ FlowContext traversedContext = flowContext;
+ int subCount = 0;
+ this.subroutines = new SubRoutineStatement[5];
+
+ do {
+ SubRoutineStatement sub;
+ if ((sub = traversedContext.subroutine()) != null) {
+ if (subCount == this.subroutines.length) {
+ System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow
+ }
+ this.subroutines[subCount++] = sub;
+ if (sub.isSubRoutineEscaping()) {
+ break;
+ }
+ }
+ traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+ traversedContext.recordBreakTo(targetContext);
+
+ if (traversedContext instanceof InsideSubRoutineFlowContext) {
+ ASTNode node = traversedContext.associatedNode;
+ if (node instanceof TryStatement) {
+ TryStatement tryStatement = (TryStatement) node;
+ flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
+ }
+ } else if (traversedContext == targetContext) {
+ // only record break info once accumulated through subroutines, and only against target context
+ targetContext.recordBreakFrom(flowInfo);
+ break;
+ }
+ } while ((traversedContext = traversedContext.parent) != null);
+
+ // resize subroutines
+ if (subCount != this.subroutines.length) {
+ System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount);
+ }
+ return FlowInfo.DEAD_END;
+}
+
+public StringBuffer printStatement(int tab, StringBuffer output) {
+ printIndent(tab, output).append("break "); //$NON-NLS-1$
+ if (this.label != null) output.append(this.label);
+ return output.append(';');
+}
+
+public void traverse(ASTVisitor visitor, BlockScope blockscope) {
+ visitor.visit(this, blockscope);
+ visitor.endVisit(this, blockscope);
+}
+public int getASTType() {
+ return IASTNode.BREAK_STATEMENT;
+
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CaseStatement.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CaseStatement.java
new file mode 100644
index 0000000..973f438
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CaseStatement.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.ICaseStatement;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CaseStatement extends Statement implements ICaseStatement {
+
+ public Expression constantExpression;
+
+ public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
+ this.constantExpression = constantExpression;
+ this.sourceEnd = sourceEnd;
+ this.sourceStart = sourceStart;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ if (constantExpression != null) {
+ this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
+ }
+ return flowInfo;
+ }
+
+ public StringBuffer printStatement(int tab, StringBuffer output) {
+
+ printIndent(tab, output);
+ if (constantExpression == null) {
+ output.append("default : "); //$NON-NLS-1$
+ } else {
+ output.append("case "); //$NON-NLS-1$
+ constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
+ }
+ return output.append(';');
+ }
+
+
+ /**
+ * No-op : should use resolveCase(...) instead.
+ */
+ public void resolve(BlockScope scope) {
+ // no-op : should use resolveCase(...) instead.
+ }
+
+ /**
+ * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
+ * @see org.eclipse.wst.jsdt.internal.compiler.ast.Statement#resolveCase(org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding, org.eclipse.wst.jsdt.internal.compiler.ast.SwitchStatement)
+ */
+ public Constant resolveCase(BlockScope scope, TypeBinding switchExpressionType, SwitchStatement switchStatement) {
+ // switchExpressionType maybe null in error case
+ scope.enclosingCase = this; // record entering in a switch case block
+
+ if (constantExpression == null) {
+ // remember the default case into the associated switch statement
+ if (switchStatement.defaultCase != null)
+ scope.problemReporter().duplicateDefaultCase(this);
+
+ // on error the last default will be the selected one ...
+ switchStatement.defaultCase = this;
+ return Constant.NotAConstant;
+ }
+ // add into the collection of cases of the associated switch statement
+ switchStatement.cases[switchStatement.caseCount++] = this;
+
+ TypeBinding caseType = constantExpression.resolveType(scope);
+ if (caseType == null || switchExpressionType == null) return Constant.NotAConstant;
+ if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
+ || caseType.isCompatibleWith(switchExpressionType)) {
+
+ return constantExpression.constant;
+
+ } else if (scope.isBoxingCompatibleWith(caseType, switchExpressionType)
+ || (caseType.isBaseType() // narrowing then boxing ?
+ && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
+ && !switchExpressionType.isBaseType()
+ && constantExpression.isConstantValueOfTypeAssignableToType(caseType, scope.environment().computeBoxingType(switchExpressionType)))) {
+ // constantExpression.computeConversion(scope, caseType, switchExpressionType); - do not report boxing/unboxing conversion
+ return constantExpression.constant;
+ }
+ scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
+ return Constant.NotAConstant;
+ }
+
+
+ public void traverse(
+ ASTVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ if (constantExpression != null) constantExpression.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+ public int getASTType() {
+ return IASTNode.CASE_STATEMENT;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ClassLiteralAccess.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ClassLiteralAccess.java
new file mode 100644
index 0000000..6d8cb62
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class ClassLiteralAccess extends Expression {
+
+ public TypeReference type;
+ public TypeBinding targetType;
+
+ public ClassLiteralAccess(int sourceEnd, TypeReference type) {
+ this.type = type;
+ type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
+ this.sourceStart = type.sourceStart;
+ this.sourceEnd = sourceEnd;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ return flowInfo;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+
+ return type.print(0, output).append(".class"); //$NON-NLS-1$
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ constant = Constant.NotAConstant;
+ if ((targetType = type.resolveType(scope, true /* check bounds*/)) == null)
+ return null;
+
+ ReferenceBinding classType = scope.getJavaLangClass();
+ this.resolvedType = classType;
+
+ return this.resolvedType;
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ type.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+ public int getASTType() {
+ return IASTNode.CLASS_LITERAL_ACCESS;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Clinit.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Clinit.java
new file mode 100644
index 0000000..3e4aa63
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/Clinit.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.flow.ExceptionHandlingFlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.flow.InitializationFlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.Parser;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortMethod;
+
+public class Clinit extends AbstractMethodDeclaration {
+
+ public Clinit(CompilationResult compilationResult) {
+ super(compilationResult);
+ modifiers = 0;
+ selector = TypeConstants.CLINIT;
+ }
+
+ public FlowInfo analyseCode(
+ Scope classScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ InitializationFlowContext staticInitializerFlowContext =(InitializationFlowContext)flowContext;
+ if (ignoreFurtherInvestigation)
+ return flowInfo;
+ try {
+ ExceptionHandlingFlowContext clinitContext =
+ new ExceptionHandlingFlowContext(
+ staticInitializerFlowContext.parent,
+ this,
+ Binding.NO_EXCEPTIONS,
+ scope,
+ FlowInfo.DEAD_END);
+
+ // check for missing returning path
+ this.needFreeReturn = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0;
+
+
+ // check missing blank final field initializations
+ flowInfo = flowInfo.mergedWith(staticInitializerFlowContext.initsOnReturn);
+
+ // check static initializers thrown exceptions
+ staticInitializerFlowContext.checkInitializerExceptions(
+ scope,
+ clinitContext,
+ flowInfo);
+ } catch (AbortMethod e) {
+ this.ignoreFurtherInvestigation = true;
+ }
+ return flowInfo;
+ }
+
+ public boolean isClinit() {
+
+ return true;
+ }
+
+ public boolean isInitializationMethod() {
+
+ return true;
+ }
+
+ public boolean isStatic() {
+
+ return true;
+ }
+
+ public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+ //the clinit is filled by hand ....
+ }
+
+ public StringBuffer print(int tab, StringBuffer output) {
+
+ printIndent(tab, output).append("()"); //$NON-NLS-1$
+ printBody(tab + 1, output);
+ return output;
+ }
+
+ public void resolve(ClassScope classScope) {
+
+ this.scope = new MethodScope(classScope, classScope.referenceContext, true);
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ ClassScope classScope) {
+
+ visitor.visit(this, classScope);
+ visitor.endVisit(this, classScope);
+ }
+
+ public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding, boolean needClassLiteralField) {
+
+ // we need to add the field right now, because the field infos are generated before the methods
+ if (needClassLiteralField) {
+ SourceTypeBinding sourceType =
+ this.scope.outerMostClassScope().enclosingSourceType();
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334
+ }
+ }
+ public int getASTType() {
+ return IASTNode.CL_INIT;
+
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CombinedBinaryExpression.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CombinedBinaryExpression.java
new file mode 100644
index 0000000..67b5e18
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CombinedBinaryExpression.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Michael Spector Bug 242754
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.ICombinedBinaryExpression;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeIds;
+
+/**
+ * CombinedBinaryExpression is an implementation of BinaryExpression that
+ * specifically attempts to mitigate the issues raised by expressions which
+ * have a very deep leftmost branch. It does so by maintaining a table of
+ * direct references to its subexpressions, and implementing non-recursive
+ * variants of the most significant recursive algorithms of its ancestors.
+ * The subexpressions table only holds intermediate binary expressions. Its
+ * role is to provide the reversed navigation through the left relationship
+ * of BinaryExpression to Expression. To cope with potentially very deep
+ * left branches, an instance of CombinedBinaryExpression is created once in
+ * a while, using variable thresholds held by {@link #arityMax}.
+ * As a specific case, the topmost node of all binary expressions that are
+ * deeper than one is a CombinedBinaryExpression, but it has no references
+ * table.
+ * Notes:
+ *
+ * - CombinedBinaryExpression is not meant to behave in other ways than
+ * BinaryExpression in any observable respect;
+ * - visitors that implement their own traversal upon binary expressions
+ * should consider taking advantage of combined binary expressions, or
+ * else face a risk of StackOverflowError upon deep instances;
+ * - callers that need to change the operator should rebuild the expression
+ * from scratch, or else amend the references table as needed to cope with
+ * the resulting, separated expressions.
+ *
+ */
+public class CombinedBinaryExpression extends BinaryExpression implements ICombinedBinaryExpression {
+
+ /**
+ * The number of consecutive binary expressions of this' left branch that
+ * bear the same operator as this.
+ * Notes:
+ * - the presence of a CombinedBinaryExpression instance resets
+ * arity, even when its operator is compatible;
+ * - this property is maintained by the parser.
+ *
+ */
+ public int arity;
+
+ /**
+ * The threshold that will trigger the creation of the next full-fledged
+ * CombinedBinaryExpression. This field is only maintained for the
+ * topmost binary expression (it is 0 otherwise). It enables a variable
+ * policy, which scales better with very large expressions.
+ */
+ public int arityMax;
+
+ /**
+ * Upper limit for {@link #arityMax}.
+ */
+ public static final int ARITY_MAX_MAX = 160;
+
+ /**
+ * Default lower limit for {@link #arityMax}.
+ */
+ public static final int ARITY_MAX_MIN = 20;
+
+ /**
+ * Default value for the first term of the series of {@link #arityMax}
+ * values. Changing this allows for experimentation. Not meant to be
+ * changed during a parse operation.
+ */
+ public static int defaultArityMaxStartingValue = ARITY_MAX_MIN;
+
+ /**
+ * A table of references to the binary expressions of this' left branch.
+ * Instances of CombinedBinaryExpression are not repeated here. Instead,
+ * the left subexpression of referencesTable[0] may be a combined binary
+ * expression, if appropriate. Null when this only cares about tracking
+ * the expression's arity.
+ */
+ public BinaryExpression referencesTable[];
+
+/**
+ * Make a new CombinedBinaryExpression. If arity is strictly greater than one,
+ * a references table is built and initialized with the reverse relationship of
+ * the one defined by {@link BinaryExpression#left}. arity and left must be
+ * compatible with each other (that is, there must be at least arity - 1
+ * consecutive compatible binary expressions into the leftmost branch of left,
+ * the topmost of which being left's immediate left expression).
+ * @param left the left branch expression
+ * @param right the right branch expression
+ * @param operator the operator for this binary expression - only PLUS for now
+ * @param arity the number of binary expressions of a compatible operator that
+ * already exist into the leftmost branch of left (including left); must
+ * be strictly greater than 0
+ */
+public CombinedBinaryExpression(Expression left, Expression right, int operator,
+ int arity) {
+ super(left, right, operator);
+ this.arity = arity;
+ if (arity > 1) {
+ this.referencesTable = new BinaryExpression[arity];
+ this.referencesTable[arity - 1] = (BinaryExpression) left;
+ for (int i = arity - 1; i > 0; i--) {
+ this.referencesTable[i - 1] =
+ (BinaryExpression) this.referencesTable[i].left;
+ }
+ } else {
+ this.arityMax = defaultArityMaxStartingValue;
+ }
+}
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
+ FlowInfo flowInfo) {
+ // keep implementation in sync with BinaryExpression#analyseCode
+ if (this.referencesTable == null) {
+ return super.analyseCode(currentScope, flowContext, flowInfo);
+ }
+ if (this.referencesTable[0] != null && this.referencesTable[0].resolvedType != null) {
+ BinaryExpression cursor;
+ if ((cursor = this.referencesTable[0]).resolvedType.id !=
+ TypeIds.T_JavaLangString) {
+ cursor.left.checkNPE(currentScope, flowContext, flowInfo);
+ }
+ flowInfo = cursor.left.analyseCode(currentScope, flowContext, flowInfo).
+ unconditionalInits();
+ for (int i = 0, end = this.arity; i < end; i ++) {
+ if ((cursor = this.referencesTable[i]).resolvedType.id !=
+ TypeIds.T_JavaLangString) {
+ cursor.right.checkNPE(currentScope, flowContext, flowInfo);
+ }
+ flowInfo = cursor.right.
+ analyseCode(currentScope, flowContext, flowInfo).
+ unconditionalInits();
+ }
+ }
+ if (this.resolvedType.id != TypeIds.T_JavaLangString) {
+ this.right.checkNPE(currentScope, flowContext, flowInfo);
+ }
+ return this.right.analyseCode(currentScope, flowContext, flowInfo).
+ unconditionalInits();
+}
+
+public StringBuffer printExpressionNoParenthesis(int indent,
+ StringBuffer output) {
+ // keep implementation in sync with
+ // BinaryExpression#printExpressionNoParenthesis and
+ // OperatorExpression#printExpression
+ if (this.referencesTable == null) {
+ return super.printExpressionNoParenthesis(indent, output);
+ }
+ String operatorString = operatorToString();
+ for (int i = this.arity - 1; i >= 0; i--) {
+ output.append('(');
+ }
+ output = this.referencesTable[0].left.
+ printExpression(indent, output);
+ for (int i = 0, end = this.arity;
+ i < end; i++) {
+ output.append(' ').append(operatorString).append(' ');
+ output = this.referencesTable[i].right.
+ printExpression(0, output);
+ output.append(')');
+ }
+ output.append(' ').append(operatorString).append(' ');
+ return this.right.printExpression(0, output);
+}
+
+public TypeBinding resolveType(BlockScope scope) {
+ // keep implementation in sync with BinaryExpression#resolveType
+ if (this.referencesTable == null) {
+ return super.resolveType(scope);
+ }
+ BinaryExpression cursor = this.referencesTable[0];
+ cursor.left.resolveType(scope);
+ for (int i = 0, end = this.arity; i < end; i ++) {
+ this.referencesTable[i].nonRecursiveResolveTypeUpwards(scope);
+ }
+ nonRecursiveResolveTypeUpwards(scope);
+ return this.resolvedType;
+}
+
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (this.referencesTable == null) {
+ super.traverse(visitor, scope);
+ } else {
+ if (visitor.visit(this, scope)) {
+ int restart;
+ for (restart = this.arity - 1;
+ restart >= 0;
+ restart--) {
+ if (!visitor.visit(
+ this.referencesTable[restart], scope)) {
+ visitor.endVisit(
+ this.referencesTable[restart], scope);
+ break;
+ }
+ }
+ restart++;
+ // restart now points to the deepest BE for which
+ // visit returned true, if any
+ if (restart == 0) {
+ this.referencesTable[0].left.traverse(visitor, scope);
+ }
+ for (int i = restart, end = this.arity;
+ i < end; i++) {
+ this.referencesTable[i].right.traverse(visitor, scope);
+ visitor.endVisit(this.referencesTable[i], scope);
+ }
+ this.right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
+
+/**
+ * Change {@link #arityMax} if and as needed. The current policy is to double
+ * arityMax each time this method is called, until it reaches
+ * {@link #ARITY_MAX_MAX}. Other policies may consider incrementing it less
+ * agressively. Call only after an appropriate value has been assigned to
+ * {@link #left}.
+ */
+// more sophisticate increment policies would leverage the leftmost expression
+// to hold an indication of the number of uses of a given arityMax in a row
+public void tuneArityMax() {
+ if (this.arityMax < ARITY_MAX_MAX) {
+ this.arityMax *= 2;
+ }
+}
+public int getASTType() {
+ return IASTNode.COMBINED_BINARY_EXPRESSION;
+
+}
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CompilationUnitDeclaration.java
new file mode 100644
index 0000000..f3d6f01
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -0,0 +1,696 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.IProgramElement;
+import org.eclipse.wst.jsdt.core.ast.IScriptFileDeclaration;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.compiler.CharOperation;
+import org.eclipse.wst.jsdt.core.infer.IInferenceFile;
+import org.eclipse.wst.jsdt.core.infer.InferredMethod;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.CompilationResult;
+import org.eclipse.wst.jsdt.internal.compiler.DelegateASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.wst.jsdt.internal.compiler.parser.NLSTag;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortMethod;
+import org.eclipse.wst.jsdt.internal.compiler.problem.AbortType;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
+
+public class CompilationUnitDeclaration
+ extends ASTNode
+ implements ProblemSeverities, ReferenceContext, IScriptFileDeclaration, IInferenceFile {
+
+ private static final Comparator STRING_LITERAL_COMPARATOR = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ StringLiteral literal1 = (StringLiteral) o1;
+ StringLiteral literal2 = (StringLiteral) o2;
+ return literal1.sourceStart - literal2.sourceStart;
+ }
+ };
+ private static final int STRING_LITERALS_INCREMENT = 10;
+
+ public ImportReference currentPackage;
+ public ImportReference[] imports;
+ public TypeDeclaration[] types;
+ public ProgramElement[] statements;
+ public int[][] comments;
+
+
+ public InferredType [] inferredTypes = new InferredType[10];
+ public int numberInferredTypes=0;
+ public HashtableOfObject inferredTypesHash=new HashtableOfObject();
+ public boolean typesHaveBeenInferred=false;
+
+ public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
+ public boolean ignoreMethodBodies = false;
+ public CompilationUnitScope scope;
+ public ProblemReporter problemReporter;
+ public CompilationResult compilationResult;
+
+
+ public LocalTypeBinding[] localTypes;
+ public int localTypeCount = 0;
+
+ public CompilationUnitBinding compilationUnitBinding;
+
+
+ public boolean isPropagatingInnerClassEmulation;
+
+ public Javadoc javadoc; // 1.5 addition for package-info.js
+
+ public NLSTag[] nlsTags;
+ private StringLiteral[] stringLiterals;
+ private int stringLiteralsPtr;
+
+
+
+ public CompilationUnitDeclaration(
+ ProblemReporter problemReporter,
+ CompilationResult compilationResult,
+ int sourceLength) {
+
+ this.problemReporter = problemReporter;
+ this.compilationResult = compilationResult;
+
+ //by definition of a compilation unit....
+ sourceStart = 0;
+ sourceEnd = sourceLength - 1;
+// System.out.println("create "+hashCode());
+ }
+
+ /*
+ * We cause the compilation task to abort to a given extent.
+ */
+ public void abort(int abortLevel, CategorizedProblem problem) {
+
+ switch (abortLevel) {
+ case AbortType :
+ throw new AbortType(this.compilationResult, problem);
+ case AbortMethod :
+ throw new AbortMethod(this.compilationResult, problem);
+ default :
+ throw new AbortCompilationUnit(this.compilationResult, problem);
+ }
+ }
+
+ /*
+ * Dispatch code analysis AND request saturation of inner emulation
+ */
+ public void analyseCode() {
+
+ if (ignoreFurtherInvestigation )
+ return;
+ try {
+ if (types != null) {
+ for (int i = 0, count = types.length; i < count; i++) {
+ types[i].analyseCode(scope);
+ }
+ }
+
+ this.scope.temporaryAnalysisIndex=0;
+ int maxVars=this.scope.localIndex;
+ for (Iterator iter = this.scope.externalCompilationUnits.iterator(); iter.hasNext();) {
+ CompilationUnitScope externalScope = (CompilationUnitScope) iter.next();
+ externalScope.temporaryAnalysisIndex=maxVars;
+ maxVars+=externalScope.localIndex;
+ }
+ FlowInfo flowInfo=FlowInfo.initial(maxVars);
+ FlowContext flowContext = new FlowContext(null, this);
+
+ if (statements != null) {
+ List functions = null;
+ for (int i = 0, length = this.statements.length; i < length; i++) {
+ // if this is not a function then analyse it
+ if(!(this.statements[i] instanceof AbstractMethodDeclaration)) {
+ flowInfo=((Statement)statements[i]).analyseCode(scope,flowContext,flowInfo);
+ } else {
+ // if this is a function then store it until all non functions are finished
+ if(functions == null)
+ functions = new ArrayList();
+ functions.add(statements[i]);
+ }
+ }
+ if(functions != null) {
+ for(int f = 0; f < functions.size(); f++) {
+ ((Statement)functions.get(f)).analyseCode(this.scope, null, flowInfo.copy());
+ }
+ }
+
+// for (int i = 0, count = statements.length; i < count; i++) {
+// if (statements[i] instanceof AbstractMethodDeclaration)
+// {
+// ((AbstractMethodDeclaration)statements[i]).analyseCode(this.scope, null, flowInfo.copy());
+// }
+// else
+// flowInfo=((Statement)statements[i]).analyseCode(scope,flowContext,flowInfo);
+// }
+ }
+ } catch (AbortCompilationUnit e) {
+ this.ignoreFurtherInvestigation = true;
+ return;
+ }
+ }
+
+ /*
+ * When unit result is about to be accepted, removed back pointers
+ * to compiler structures.
+ */
+ public void cleanUp() {
+ if (this.compilationUnitBinding!=null)
+
+ this.compilationUnitBinding.cleanup();
+ if (this.types != null) {
+ for (int i = 0, max = this.types.length; i < max; i++) {
+ cleanUp(this.types[i]);
+ }
+ for (int i = 0, max = this.localTypeCount; i < max; i++) {
+ LocalTypeBinding localType = localTypes[i];
+ // null out the type's scope backpointers
+ localType.scope = null; // local members are already in the list
+ localType.enclosingCase = null;
+ }
+ }
+
+ for (int i = 0; i < this.numberInferredTypes; i++) {
+ SourceTypeBinding binding = this.inferredTypes[i].binding;
+ if (binding!=null)
+ binding.cleanup();
+ }
+ compilationResult.recoveryScannerData = null; // recovery is already done
+
+
+ }
+ private void cleanUp(TypeDeclaration type) {
+ if (type.memberTypes != null) {
+ for (int i = 0, max = type.memberTypes.length; i < max; i++){
+ cleanUp(type.memberTypes[i]);
+ }
+ }
+ if (type.binding != null) {
+ // null out the type's scope backpointers
+ type.binding.scope = null;
+ }
+ }
+
+ public CompilationResult compilationResult() {
+ return this.compilationResult;
+ }
+
+ /*
+ * Finds the matching type amoung this compilation unit types.
+ * Returns null if no type with this name is found.
+ * The type name is a compound name
+ * eg. if we're looking for X.A.B then a type name would be {X, A, B}
+ */
+ public TypeDeclaration declarationOfType(char[][] typeName) {
+
+ for (int i = 0; i < this.types.length; i++) {
+ TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
+ if (typeDecl != null) {
+ return typeDecl;
+ }
+ }
+ return null;
+ }
+
+
+ public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
+ if (methodBinding != null && this.statements != null) {
+ for (int i = 0, max = this.statements.length; i < max; i++) {
+ if (this.statements[i] instanceof AbstractMethodDeclaration)
+ {
+ AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)this.statements[i];
+ if (methodDecl.binding == methodBinding)
+ return methodDecl;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ public char[] getFileName() {
+
+ return compilationResult.getFileName();
+ }
+
+ public char[] getMainTypeName() {
+
+ if (compilationResult.compilationUnit == null) {
+ char[] fileName = compilationResult.getFileName();
+
+ int start = CharOperation.lastIndexOf('/', fileName) + 1;
+ if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
+ start = CharOperation.lastIndexOf('\\', fileName) + 1;
+
+ int end = CharOperation.lastIndexOf('.', fileName);
+ if (end == -1)
+ end = fileName.length;
+
+ return CharOperation.subarray(fileName, start, end);
+ } else {
+ return compilationResult.compilationUnit.getMainTypeName();
+ }
+ }
+
+ public boolean isEmpty() {
+
+ return (currentPackage == null) && (imports == null) && (types == null) && (statements==null);
+ }
+
+ public boolean isPackageInfo() {
+ return CharOperation.equals(this.getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME);
+ }
+
+ public boolean hasErrors() {
+ return this.ignoreFurtherInvestigation;
+ }
+
+ public StringBuffer print(int indent, StringBuffer output) {
+
+ if (currentPackage != null) {
+ printIndent(indent, output).append("package "); //$NON-NLS-1$
+ currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
+ }
+ if (imports != null)
+ for (int i = 0; i < imports.length; i++) {
+ if (imports[i].isInternal())
+ continue;
+ printIndent(indent, output).append("import "); //$NON-NLS-1$
+ ImportReference currentImport = imports[i];
+ currentImport.print(0, output).append(";\n"); //$NON-NLS-1$
+ }
+
+ if (types != null) {
+ for (int i = 0; i < types.length; i++) {
+ types[i].print(indent, output).append("\n"); //$NON-NLS-1$
+ }
+ }
+ if (statements != null) {
+ for (int i = 0; i < statements.length; i++) {
+ statements[i].printStatement(indent, output).append("\n"); //$NON-NLS-1$
+ }
+ }
+ return output;
+ }
+
+ public void recordStringLiteral(StringLiteral literal) {
+ if (this.stringLiterals == null) {
+ this.stringLiterals = new StringLiteral[STRING_LITERALS_INCREMENT];
+ this.stringLiteralsPtr = 0;
+ } else {
+ int stackLength = this.stringLiterals.length;
+ if (this.stringLiteralsPtr == stackLength) {
+ System.arraycopy(
+ this.stringLiterals,
+ 0,
+ this.stringLiterals = new StringLiteral[stackLength + STRING_LITERALS_INCREMENT],
+ 0,
+ stackLength);
+ }
+ }
+ this.stringLiterals[this.stringLiteralsPtr++] = literal;
+ }
+
+ /*
+ * Keep track of all local types, so as to update their innerclass
+ * emulation later on.
+ */
+ public void record(LocalTypeBinding localType) {
+
+ if (this.localTypeCount == 0) {
+ this.localTypes = new LocalTypeBinding[5];
+ } else if (this.localTypeCount == this.localTypes.length) {
+ System.arraycopy(this.localTypes, 0, (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]), 0, this.localTypeCount);
+ }
+ this.localTypes[this.localTypeCount++] = localType;
+ }
+
+ public void resolve() {
+ int startingTypeIndex = 0;
+ boolean isPackageInfo = false;//isPackageInfo();
+ if (this.types != null && isPackageInfo) {
+ // resolve synthetic type declaration
+ final TypeDeclaration syntheticTypeDeclaration = types[0];
+ // set empty javadoc to avoid missing warning (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=95286)
+ if (syntheticTypeDeclaration.javadoc == null) {
+ syntheticTypeDeclaration.javadoc = new Javadoc(syntheticTypeDeclaration.declarationSourceStart, syntheticTypeDeclaration.declarationSourceStart);
+ }
+ syntheticTypeDeclaration.resolve(this.scope);
+ // resolve annotations if any
+// if (this.currentPackage!= null && this.currentPackage.annotations != null) {
+// resolveAnnotations(syntheticTypeDeclaration.staticInitializerScope, this.currentPackage.annotations, this.scope.getDefaultPackage());
+// }
+ // resolve javadoc package if any
+ if (this.javadoc != null) {
+ this.javadoc.resolve(syntheticTypeDeclaration.staticInitializerScope);
+ }
+ startingTypeIndex = 1;
+ } else {
+ // resolve compilation unit javadoc package if any
+ if (this.javadoc != null) {
+ this.javadoc.resolve(this.scope);
+ }
+ }
+
+ try {
+ if (types != null) {
+ for (int i = startingTypeIndex, count = types.length; i < count; i++) {
+ types[i].resolve(scope);
+ }
+ }
+ if (statements != null) {
+ for (int i = 0, count = statements.length; i < count; i++) {
+ statements[i].resolve(scope);
+ }
+ }
+ reportNLSProblems();
+ } catch (AbortCompilationUnit e) {
+ this.ignoreFurtherInvestigation = true;
+ return;
+ }
+ }
+
+ public void resolve(int start, int end) {
+ try {
+ int startingTypeIndex = 0;
+ // resolve compilation unit javadoc package if any
+ if (this.javadoc != null && this.javadoc.sourceStart<=start && this.javadoc.sourceEnd>= end) {
+ this.javadoc.resolve(this.scope);
+ }
+ if (types != null) {
+ for (int i = startingTypeIndex, count = types.length; i < count; i++) {
+ TypeDeclaration typeDeclaration = types[i];
+ if (typeDeclaration.sourceStart<=start && typeDeclaration.sourceEnd>=end)
+ typeDeclaration.resolve(scope);
+ }
+ }
+ if (statements != null) {
+ for (int i = 0, count = statements.length; i < count; i++) {
+ ProgramElement programElement = statements[i];
+ if (programElement.sourceStart<=start && programElement.sourceEnd>=end)
+ programElement.resolve(scope);
+ }
+ }
+ reportNLSProblems();
+ } catch (AbortCompilationUnit e) {
+ this.ignoreFurtherInvestigation = true;
+ return;
+ }
+ }
+
+
+ private void reportNLSProblems() {
+ if (this.nlsTags != null || this.stringLiterals != null) {
+ final int stringLiteralsLength = this.stringLiteralsPtr;
+ final int nlsTagsLength = this.nlsTags == null ? 0 : this.nlsTags.length;
+ if (stringLiteralsLength == 0) {
+ if (nlsTagsLength != 0) {
+ for (int i = 0; i < nlsTagsLength; i++) {
+ NLSTag tag = this.nlsTags[i];
+ if (tag != null) {
+ scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end);
+ }
+ }
+ }
+ } else if (nlsTagsLength == 0) {
+ // resize string literals
+ if (this.stringLiterals.length != stringLiteralsLength) {
+ System.arraycopy(this.stringLiterals, 0, (stringLiterals = new StringLiteral[stringLiteralsLength]), 0, stringLiteralsLength);
+ }
+ Arrays.sort(this.stringLiterals, STRING_LITERAL_COMPARATOR);
+ for (int i = 0; i < stringLiteralsLength; i++) {
+ scope.problemReporter().nonExternalizedStringLiteral(this.stringLiterals[i]);
+ }
+ } else {
+ // need to iterate both arrays to find non matching elements
+ if (this.stringLiterals.length != stringLiteralsLength) {
+ System.arraycopy(this.stringLiterals, 0, (stringLiterals = new StringLiteral[stringLiteralsLength]), 0, stringLiteralsLength);
+ }
+ Arrays.sort(this.stringLiterals, STRING_LITERAL_COMPARATOR);
+ int indexInLine = 1;
+ int lastLineNumber = -1;
+ StringLiteral literal = null;
+ int index = 0;
+ int i = 0;
+ stringLiteralsLoop: for (; i < stringLiteralsLength; i++) {
+ literal = this.stringLiterals[i];
+ final int literalLineNumber = literal.lineNumber;
+ if (lastLineNumber != literalLineNumber) {
+ indexInLine = 1;
+ lastLineNumber = literalLineNumber;
+ } else {
+ indexInLine++;
+ }
+ if (index < nlsTagsLength) {
+ nlsTagsLoop: for (; index < nlsTagsLength; index++) {
+ NLSTag tag = this.nlsTags[index];
+ if (tag == null) continue nlsTagsLoop;
+ int tagLineNumber = tag.lineNumber;
+ if (literalLineNumber < tagLineNumber) {
+ scope.problemReporter().nonExternalizedStringLiteral(literal);
+ continue stringLiteralsLoop;
+ } else if (literalLineNumber == tagLineNumber) {
+ if (tag.index == indexInLine) {
+ this.nlsTags[index] = null;
+ index++;
+ continue stringLiteralsLoop;
+ } else {
+ nlsTagsLoop2: for (int index2 = index + 1; index2 < nlsTagsLength; index2++) {
+ NLSTag tag2 = this.nlsTags[index2];
+ if (tag2 == null) continue nlsTagsLoop2;
+ int tagLineNumber2 = tag2.lineNumber;
+ if (literalLineNumber == tagLineNumber2) {
+ if (tag2.index == indexInLine) {
+ this.nlsTags[index2] = null;
+ continue stringLiteralsLoop;
+ } else {
+ continue nlsTagsLoop2;
+ }
+ } else {
+ scope.problemReporter().nonExternalizedStringLiteral(literal);
+ continue stringLiteralsLoop;
+ }
+ }
+ scope.problemReporter().nonExternalizedStringLiteral(literal);
+ continue stringLiteralsLoop;
+ }
+ } else {
+ scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end);
+ continue nlsTagsLoop;
+ }
+ }
+ }
+ // all nls tags have been processed, so remaining string literals are not externalized
+ break stringLiteralsLoop;
+ }
+ for (; i < stringLiteralsLength; i++) {
+ scope.problemReporter().nonExternalizedStringLiteral(this.stringLiterals[i]);
+ }
+ if (index < nlsTagsLength) {
+ for (; index < nlsTagsLength; index++) {
+ NLSTag tag = this.nlsTags[index];
+ if (tag != null) {
+ scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void tagAsHavingErrors() {
+ ignoreFurtherInvestigation = true;
+ }
+
+
+ public void traverse(org.eclipse.wst.jsdt.core.ast.ASTVisitor visitor)
+ {
+ this.traverse(new DelegateASTVisitor(visitor), null,false);
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ CompilationUnitScope unitScope) {
+ traverse(visitor, scope,false);
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ CompilationUnitScope unitScope, boolean ignoreErrors) {
+
+ if (ignoreFurtherInvestigation && !ignoreErrors)
+ return;
+ try {
+ if (visitor.visit(this, this.scope)) {
+ if (this.types != null && isPackageInfo()) {
+ // resolve synthetic type declaration
+ final TypeDeclaration syntheticTypeDeclaration = types[0];
+ // resolve javadoc package if any
+ final MethodScope methodScope = syntheticTypeDeclaration.staticInitializerScope;
+ if (this.javadoc != null) {
+ this.javadoc.traverse(visitor, methodScope);
+ }
+ }
+
+// if (currentPackage != null) {
+// currentPackage.traverse(visitor, this.scope);
+// }
+// if (imports != null) {
+// int importLength = imports.length;
+// for (int i = 0; i < importLength; i++) {
+// imports[i].traverse(visitor, this.scope);
+// }
+// }
+// if (types != null) {
+// int typesLength = types.length;
+// for (int i = 0; i < typesLength; i++) {
+// types[i].traverse(visitor, this.scope);
+// }
+// }
+ if (statements != null) {
+ int statementsLength = statements.length;
+ for (int i = 0; i < statementsLength; i++) {
+ statements[i].traverse(visitor, this.scope);
+ }
+ }
+ traverseInferredTypes(visitor,unitScope);
+ }
+ visitor.endVisit(this, this.scope);
+ } catch (AbortCompilationUnit e) {
+ // ignore
+ }
+ }
+
+ public void traverseInferredTypes(ASTVisitor visitor,BlockScope unitScope) {
+ boolean continueVisiting=true;
+ for (int i=0;i 0)
+ {
+ if (numberInferredTypes == inferredTypes.length)
+ {
+ System.arraycopy(
+ inferredTypes,
+ 0,
+ (inferredTypes = new InferredType[numberInferredTypes * 2]),
+ 0,
+ numberInferredTypes );
+ }
+
+ type=inferredTypes[numberInferredTypes ++] = new InferredType(className);
+ type.inferenceProviderID = providerId;
+ if (className.length > 2 && className[className.length - 2] == '[' && className[className.length - 1] == ']') {
+ type.isArray = true;
+ }
+
+ inferredTypesHash.put(className,type);
+ }
+ if (isDefinition && type != null)
+ type.isDefinition=isDefinition;
+ return type;
+ }
+}
diff --git a/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CompoundAssignment.java b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CompoundAssignment.java
new file mode 100644
index 0000000..fc9711e
--- /dev/null
+++ b/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/CompoundAssignment.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.compiler.ast;
+
+import org.eclipse.wst.jsdt.core.ast.IASTNode;
+import org.eclipse.wst.jsdt.core.ast.ICompoundAssignment;
+import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
+import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
+import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
+
+public class CompoundAssignment extends Assignment implements OperatorIds, ICompoundAssignment {
+ public int operator;
+ public int preAssignImplicitConversion;
+
+ // var op exp is equivalent to var = (varType) var op exp
+ // assignmentImplicitConversion stores the cast needed for the assignment
+
+ public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) {
+ //lhs is always a reference by construction ,
+ //but is build as an expression ==> the checkcast cannot fail
+
+ super(lhs, expression, sourceEnd);
+ lhs.bits &= ~IsStrictlyAssigned; // tag lhs as NON assigned - it is also a read access
+ lhs.bits |= IsCompoundAssigned; // tag lhs as assigned by compound
+ this.operator = operator ;
+ }
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
+ FlowInfo flowInfo) {
+ // record setting a variable: various scenarii are possible, setting an array reference,
+ // a field reference, a blank final field reference, a field of an enclosing instance or
+ // just a local variable.
+ if (this.resolvedType.id != T_JavaLangString) {
+ lhs.checkNPE(currentScope, flowContext, flowInfo);
+ }
+ return ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits();
+}
+
+ public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.NON_NULL;
+ // we may have complained on checkNPE, but we avoid duplicate error
+}
+
+ public String operatorToString() {
+ switch (operator) {
+ case PLUS :
+ return "+="; //$NON-NLS-1$
+ case MINUS :
+ return "-="; //$NON-NLS-1$
+ case MULTIPLY :
+ return "*="; //$NON-NLS-1$
+ case DIVIDE :
+ return "/="; //$NON-NLS-1$
+ case AND :
+ return "&="; //$NON-NLS-1$
+ case OR :
+ return "|="; //$NON-NLS-1$
+ case XOR :
+ return "^="; //$NON-NLS-1$
+ case REMAINDER :
+ return "%="; //$NON-NLS-1$
+ case LEFT_SHIFT :
+ return "<<="; //$NON-NLS-1$
+ case RIGHT_SHIFT :
+ return ">>="; //$NON-NLS-1$
+ case UNSIGNED_RIGHT_SHIFT :
+ return ">>>="; //$NON-NLS-1$
+ }
+ return "unknown operator"; //$NON-NLS-1$
+ }
+
+ public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+ lhs.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
+ return expression.printExpression(0, output) ;
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ constant = Constant.NotAConstant;
+ if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
+ scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+ return null;
+ }
+ TypeBinding originalLhsType = lhs.resolveType(scope);
+ TypeBinding originalExpressionType = expression.resolveType(scope);
+ this.resolvedType=TypeBinding.ANY;
+ if (originalLhsType == null || originalExpressionType == null)
+ {
+ return null;
+ }
+
+ // autoboxing support
+ LookupEnvironment env = scope.environment();
+ TypeBinding lhsType = originalLhsType, expressionType = originalExpressionType;
+ boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
+ boolean unboxedLhs = false;
+ if (use15specifics) {
+ if (!lhsType.isBaseType() && expressionType.id != T_JavaLangString && expressionType.id != T_null) {
+ TypeBinding unboxedType = env.computeBoxingType(lhsType);
+ if (unboxedType != lhsType) {
+ lhsType = unboxedType;
+ unboxedLhs = true;
+ }
+ }
+ if (!expressionType.isBaseType() && lhsType.id != T_JavaLangString && lhsType.id != T_null) {
+ expressionType = env.computeBoxingType(expressionType);
+ }
+ }
+
+ if (restrainUsageToNumericTypes() && !lhsType.isNumericType() && !lhsType.isAnyType()) {
+ scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType);
+ return null;
+ }
+ int lhsID = lhsType.id;
+ int expressionID = expressionType.id;
+ if (lhsID > 15 || expressionID > 15) {
+ if (lhsID != T_JavaLangString) { // String += Thread is valid whereas Thread += String is not
+ scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+ return null;
+ }
+ expressionID = T_JavaLangObject; // use the Object has tag table
+ }
+
+ // the code is an int
+ // (cast) left Op (cast) rigth --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+
+ // the conversion is stored INTO the reference (info needed for the code gen)
+ int result = OperatorExpression.OperatorSignatures[operator][ (lhsID << 4) + expressionID];
+ if (result == T_undefined) {
+ scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+ return null;
+ }
+// if (operator == PLUS){
+// if(lhsID == T_JavaLangObject) {
+// //