@@ -0,0 +1,123 @@
/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.js.parsing;

import java.util.Stack;

import com.aptana.core.logging.IdeLog;
import com.aptana.editor.js.JSPlugin;
import com.aptana.parsing.ParseState;

/**
* JSParseState
*/
public class JSParseState extends ParseState
{
private static class CommentContext
{
boolean collectComments;
boolean attachComments;

public CommentContext()
{
collectComments = true;
attachComments = true;
}

public CommentContext(CommentContext oldContext)
{
collectComments = oldContext.collectComments;
attachComments = oldContext.attachComments;
}
}

private Stack<CommentContext> commentContentStack;

/**
* JSParseState
*/
public JSParseState()
{
commentContentStack = new Stack<CommentContext>();

commentContentStack.push(new CommentContext());
}

/**
* attachComments
*
* @return
*/
public boolean attachComments()
{
return getCurrentCommentContext().attachComments;
}

/**
* collectComments
*
* @return
*/
public boolean collectComments()
{
return getCurrentCommentContext().attachComments;
}

/**
* getCurrentCommentContext
*
* @return
*/
protected CommentContext getCurrentCommentContext()
{
return commentContentStack.peek();
}

/**
* popCommentText
*/
public void popCommentContext()
{
if (commentContentStack.size() > 1)
{
commentContentStack.pop();
}
else
{
IdeLog.logError(JSPlugin.getDefault(), "Tried to pop an empty comment context stack in JSParseState"); //$NON-NLS-1$
}
}

/**
* pushCommentContext
*/
public void pushCommentContext()
{
commentContentStack.push(new CommentContext(getCurrentCommentContext()));
}

/**
* setAttachComments
*
* @param flag
*/
public void setAttachComments(boolean flag)
{
commentContentStack.peek().attachComments = flag;
}

/**
* setCollectComments
*
* @param flag
*/
public void setCollectComments(boolean flag)
{
commentContentStack.peek().attachComments = flag;
}
}
@@ -419,43 +419,41 @@ public synchronized IParseRootNode parse(IParseState parseState) throws java.lan
// store results in the parse state
fParseState.setParseResult(result);

// TODO: We probably don't need documentation nodes in all cases. For
// example, the outline view probably doesn't rely on them. We should
// include a flag (maybe in the parseState) that makes this step
// optional.
JSParseRootNode root = (JSParseRootNode) result;

// attach documentation
if (result instanceof JSParseRootNode)
if (!(parseState instanceof JSParseState) || ((JSParseState) parseState).attachComments())
{
JSParseRootNode root = (JSParseRootNode) result;

// attach documentation
attachPreDocumentationBlocks(root, source);
attachPostDocumentationBlocks(root, source);
}

if (!(parseState instanceof JSParseState) || ((JSParseState) parseState).collectComments())
{
// create a list of all comments and attach to root node
List<JSCommentNode> comments = new ArrayList<JSCommentNode>();

for (Symbol symbol : fScanner.getSDocComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.SDOC_COMMENT, symbol.getStart(), symbol.getEnd()));
}

for (Symbol symbol : fScanner.getVSDocComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.VSDOC_COMMENT, symbol.getStart(), symbol.getEnd()));
}

for (Symbol symbol : fScanner.getSingleLineComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.SINGLE_LINE_COMMENT, symbol.getStart(), symbol.getEnd()));
}

for (Symbol symbol : fScanner.getMultiLineComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.MULTI_LINE_COMMENT, symbol.getStart(), symbol.getEnd()));
}

root.setCommentNodes(comments.toArray(new IParseNode[comments.size()]));
{
comments.add(new JSCommentNode(IJSNodeTypes.SDOC_COMMENT, symbol.getStart(), symbol.getEnd()));
}

for (Symbol symbol : fScanner.getVSDocComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.VSDOC_COMMENT, symbol.getStart(), symbol.getEnd()));
}

for (Symbol symbol : fScanner.getSingleLineComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.SINGLE_LINE_COMMENT, symbol.getStart(), symbol.getEnd()));
}

for (Symbol symbol : fScanner.getMultiLineComments())
{
comments.add(new JSCommentNode(IJSNodeTypes.MULTI_LINE_COMMENT, symbol.getStart(), symbol.getEnd()));
}

root.setCommentNodes(comments.toArray(new IParseNode[comments.size()]));
}

return result;
@@ -26,9 +26,11 @@

import com.aptana.editor.common.AbstractThemeableEditor;
import com.aptana.editor.common.tests.util.TestProject;
import com.aptana.editor.js.contentassist.index.JSFileIndexingParticipant;
import com.aptana.editor.js.contentassist.model.FunctionElement;
import com.aptana.editor.js.contentassist.model.PropertyElement;
import com.aptana.editor.js.tests.JSEditorBasedTests;
import com.aptana.index.core.IFileStoreIndexingParticipant;
import com.aptana.index.core.Index;
import com.aptana.index.core.IndexManager;
import com.aptana.scripting.model.BundleElement;
@@ -352,4 +354,14 @@ protected void assertDoesntContainFunctions(Collection<PropertyElement> projectG
fail(MessageFormat.format("Functions contain an entry for disallowed name(s): {0}", matches));
}
}

/*
* (non-Javadoc)
* @see com.aptana.editor.common.EditorBasedTests#createIndexer()
*/
@Override
protected IFileStoreIndexingParticipant createIndexer()
{
return new JSFileIndexingParticipant();
}
}
@@ -17,8 +17,6 @@

import com.aptana.core.util.IOUtil;
import com.aptana.editor.js.JSPlugin;
import com.aptana.parsing.IParseState;
import com.aptana.parsing.ParseState;

public class JSParserPerformanceTest extends PerformanceTestCase
{
@@ -187,8 +185,10 @@ private void timeParse(String resourceName, int numRuns) throws Exception
private void timeParse(String resourceName, String src, int numRuns) throws Exception
{
// apply to parse state
IParseState parseState = new ParseState();
JSParseState parseState = new JSParseState();
parseState.setEditState(src, src, 0, 0);
parseState.setAttachComments(false);
parseState.setCollectComments(false);

for (int i = 0; i < numRuns; i++)
{
@@ -0,0 +1,212 @@
/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.js.parsing;

import java.io.IOException;
import java.io.InputStream;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.test.performance.PerformanceTestCase;

import beaver.Symbol;

import com.aptana.core.util.IOUtil;
import com.aptana.editor.js.JSPlugin;
import com.aptana.parsing.IParseState;
import com.aptana.parsing.ParseState;

public class JSScannerPerformanceTest extends PerformanceTestCase
{
private JSScanner fScanner;

/**
* getSource
*
* @param stream
* @return
* @throws IOException
*/
private String getSource(InputStream stream) throws IOException
{
return IOUtil.read(stream);
}

/**
* getSource
*
* @param resourceName
* @return
* @throws IOException
*/
private String getSource(String resourceName) throws IOException
{
InputStream stream = FileLocator.openStream(Platform.getBundle(JSPlugin.PLUGIN_ID), new Path(resourceName),
false);
return getSource(stream);
}

/*
* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception
{
super.setUp();

fScanner = new JSScanner();
}

/*
* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception
{
fScanner = null;

super.tearDown();
}

/**
* testDojo
*
* @throws Exception
*/
public void testDojo() throws Exception
{
assertScan(10, "performance/dojo.js.uncompressed.js");
}

/**
* testExt
*
* @throws Exception
*/
public void testExt() throws Exception
{
assertScan(15, "performance/ext-core.js");
}

/**
* testTiMobile
*
* @throws Exception
*/
public void testTiMobile() throws Exception
{
assertScan(10, "performance/timobile.js");
}

/**
* testTinyMce
*
* @throws Exception
*/
public void testTinyMce() throws Exception
{
assertScan(10, "performance/tiny_mce.js");
}

/**
* testJaxerFiles
*
* @throws Exception
*/
public void testJaxerFiles() throws Exception
{
assertScan(5, "performance/jaxer/11.2.2-1-n.js", "performance/jaxer/15.10.6.2-2.js",
"performance/jaxer/15.5.4.7-2.js", "performance/jaxer/15.9.5.21-3.js",
"performance/jaxer/ComposerCommands.js", "performance/jaxer/DBAPI.js",
"performance/jaxer/DOMTestCase.js", "performance/jaxer/Microformats.js",
"performance/jaxer/MochiKit_packed.js", "performance/jaxer/SimpleTest.js",
"performance/jaxer/TestCachePerformance.js", "performance/jaxer/UDDITypes.js",
"performance/jaxer/browser_bug_411172.js", "performance/jaxer/clientBothProperty.js",
"performance/jaxer/commands.js", "performance/jaxer/crlManager.js", "performance/jaxer/dojo.js",
"performance/jaxer/dom.js", "performance/jaxer/editor.js", "performance/jaxer/effects.js",
"performance/jaxer/file-utils.js", "performance/jaxer/head_urlformatter.js",
"performance/jaxer/httpd.js", "performance/jaxer/ifaceinfotest.js", "performance/jaxer/irc.js",
"performance/jaxer/jquery-1.2.1.js", "performance/jaxer/jquery-1.2.6.min.js",
"performance/jaxer/jquery-stable.js", "performance/jaxer/jquery.js",
"performance/jaxer/lexical-008.js", "performance/jaxer/messages.js",
"performance/jaxer/narcissus-exec.js", "performance/jaxer/nsDragAndDrop.js",
"performance/jaxer/packed.js", "performance/jaxer/perlstress-001.js",
"performance/jaxer/perlstress-002.js", "performance/jaxer/property_database.js",
"performance/jaxer/prototype.js", "performance/jaxer/publishprefs.js",
"performance/jaxer/regress-100199.js", "performance/jaxer/regress-111557.js",
"performance/jaxer/regress-155081-2.js", "performance/jaxer/regress-192226.js",
"performance/jaxer/regress-244470.js", "performance/jaxer/regress-309925-02.js",
"performance/jaxer/regress-76054.js", "performance/jaxer/regress-98901.js",
"performance/jaxer/scriptaculous.js", "performance/jaxer/split-002.js",
"performance/jaxer/test_413784.js", "performance/jaxer/test_423515_forceCopyShortcuts.js",
"performance/jaxer/test_bug364285-1.js", "performance/jaxer/test_bug374754.js",
"performance/jaxer/test_multi_statements.js", "performance/jaxer/test_prepare_insert_update.js",
"performance/jaxer/tip_followscroll.js", "performance/jaxer/tree-utils.js",
"performance/jaxer/utils.js", "performance/jaxer/xpath.js", "performance/jaxer/xslt_script.js");
}

/**
* assertParse
*
* @param resourceName
* @throws Exception
*/
private void assertScan(int numRuns, String... resources) throws Exception
{
for (String resourceName : resources)
{
timeScan(resourceName, numRuns);
}
commitMeasurements();
assertPerformance();
}

/**
* time
*
* @param resourceName
* @param numRuns
* @throws Exception
*/
private void timeScan(String resourceName, int numRuns) throws Exception
{
this.timeScan(resourceName, getSource(resourceName), numRuns);
}

/**
* time
*
* @param resourceName
* @throws Exception
*/
private void timeScan(String resourceName, String src, int numRuns) throws Exception
{
// apply to parse state
IParseState parseState = new ParseState();
parseState.setEditState(src, src, 0, 0);

for (int i = 0; i < numRuns; i++)
{
startMeasuring();

fScanner.setSource(src);

Symbol symbol = fScanner.nextToken();

while (symbol != null && symbol.getId() != 0)
{
symbol = fScanner.nextToken();
}

stopMeasuring();
}
}
}