diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParsePluginTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParsePluginTest.java index 4d683ec34a0..4589208bef2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParsePluginTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParsePluginTest.java @@ -14,300 +14,35 @@ */ package org.eclipse.cdt.core.parser.tests; -import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import junit.framework.Test; -import junit.framework.TestCase; import junit.framework.TestSuite; -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.parser.CodeReader; -import org.eclipse.cdt.core.parser.IParser; -import org.eclipse.cdt.core.parser.IProblem; -import org.eclipse.cdt.core.parser.ISourceElementRequestor; -import org.eclipse.cdt.core.parser.NullLogService; -import org.eclipse.cdt.core.parser.ParserFactory; -import org.eclipse.cdt.core.parser.ParserLanguage; -import org.eclipse.cdt.core.parser.ParserMode; -import org.eclipse.cdt.core.parser.ParserUtil; -import org.eclipse.cdt.core.parser.ScannerInfo; -import org.eclipse.cdt.core.parser.ast.IASTASMDefinition; -import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration; -import org.eclipse.cdt.core.parser.ast.IASTClassReference; -import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; -import org.eclipse.cdt.core.parser.ast.IASTCodeScope; -import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit; -import org.eclipse.cdt.core.parser.ast.IASTDeclaration; -import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier; -import org.eclipse.cdt.core.parser.ast.IASTEnumerationReference; -import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier; -import org.eclipse.cdt.core.parser.ast.IASTEnumeratorReference; -import org.eclipse.cdt.core.parser.ast.IASTField; -import org.eclipse.cdt.core.parser.ast.IASTFieldReference; -import org.eclipse.cdt.core.parser.ast.IASTFunction; -import org.eclipse.cdt.core.parser.ast.IASTFunctionReference; -import org.eclipse.cdt.core.parser.ast.IASTInclusion; -import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; -import org.eclipse.cdt.core.parser.ast.IASTMacro; -import org.eclipse.cdt.core.parser.ast.IASTMethod; -import org.eclipse.cdt.core.parser.ast.IASTMethodReference; -import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; -import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference; -import org.eclipse.cdt.core.parser.ast.IASTParameterReference; -import org.eclipse.cdt.core.parser.ast.IASTScope; -import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration; -import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation; -import org.eclipse.cdt.core.parser.ast.IASTTemplateParameterReference; -import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization; -import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; -import org.eclipse.cdt.core.parser.ast.IASTTypedefReference; -import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; -import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; import org.eclipse.cdt.core.parser.ast.IASTVariable; -import org.eclipse.cdt.core.parser.ast.IASTVariableReference; -import org.eclipse.cdt.internal.core.parser.Parser; -import org.eclipse.cdt.internal.core.parser.ParserException; -import org.eclipse.cdt.internal.core.search.indexing.IndexManager; -import org.eclipse.cdt.testplugin.CProjectHelper; -import org.eclipse.cdt.testplugin.FileManager; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; /** * @author aniefer */ -public class CompleteParsePluginTest extends TestCase { - static NullProgressMonitor monitor; - static IWorkspace workspace; - static IProject project; - static FileManager fileManager; - - { - if( CCorePlugin.getDefault() != null && CCorePlugin.getDefault().getCoreModel() != null){ - (CCorePlugin.getDefault().getCoreModel().getIndexManager()).reset(); - monitor = new NullProgressMonitor(); - - workspace = ResourcesPlugin.getWorkspace(); - - ICProject cPrj; - try { - cPrj = CProjectHelper.createCCProject("ParserTestProject", "bin"); //$NON-NLS-1$ //$NON-NLS-2$ - - project = cPrj.getProject(); - project.setSessionProperty(IndexManager.activationKey,new Boolean(false)); - } catch ( CoreException e ) { - /*boo*/ - } - if (project == null) - fail("Unable to create project"); //$NON-NLS-1$ +public class CompleteParsePluginTest extends FileBasePluginTest { - //Create file manager - fileManager = new FileManager(); - } - } - - public CompleteParsePluginTest() - { - super(); - } /** * @param name */ public CompleteParsePluginTest(String name) { - super(name); + super(name, CompleteParsePluginTest.class); } - + public static Test suite() { TestSuite suite = new TestSuite( CompleteParsePluginTest.class ); suite.addTest( new CompleteParsePluginTest("cleanupProject") ); //$NON-NLS-1$ return suite; } - - public void cleanupProject() throws Exception { - try{ - project.delete( true, false, monitor ); - project = null; - } catch( Throwable e ){ - /*boo*/ - } - } - - protected void tearDown() throws Exception { - if( project == null || !project.exists() ) - return; - - IResource [] members = project.members(); - for( int i = 0; i < members.length; i++ ){ - if( members[i].getName().equals( ".project" ) || members[i].getName().equals( ".cdtproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ - continue; - try{ - members[i].delete( false, monitor ); - } catch( Throwable e ){ - /*boo*/ - } - } - } - protected IFile importFile(String fileName, String contents ) throws Exception{ - //Obtain file handle - IFile file = project.getProject().getFile(fileName); - - InputStream stream = new ByteArrayInputStream( contents.getBytes() ); - //Create file input stream - if( file.exists() ) - file.setContents( stream, false, false, monitor ); - else - file.create( stream, false, monitor ); - - fileManager.addFile(file); - - return file; - } - - public static class CallbackTracker implements ISourceElementRequestor{ - private List callbacks; - private IASTScope compUnit; - public CallbackTracker( List callbacks ){ - this.callbacks = callbacks; - } - - public IASTScope getCompilationUnit() - { - return compUnit; - } - public static final String ACCEPT_PROBLEM = "ACCEPT_PROBLEM"; //$NON-NLS-1$ - public static final String ACCEPT_MACRO = "ACCEPT_MACRO"; //$NON-NLS-1$ - public static final String ACCEPT_VARIABLE = "ACCEPT_VARIABLE"; //$NON-NLS-1$ - public static final String ACCEPT_FUNCTION_DECL = "ACCEPT_FUNCTION_DECL"; //$NON-NLS-1$ - public static final String ACCEPT_USING_DIRECTIVE = "ACCEPT_USING_DIRECTIVE"; //$NON-NLS-1$ - public static final String ACCEPT_USING_DECL = "ACCEPT_USING_DECL"; //$NON-NLS-1$ - public static final String ACCEPT_ASM_DEF = "ACCEPT_ASM_DEF"; //$NON-NLS-1$ - public static final String ACCEPT_TYPEDEF = "ACCEPT_TYPEDEF"; //$NON-NLS-1$ - public static final String ACCEPT_ENUMERATION = "ACCEPT_ENUMERATION"; //$NON-NLS-1$ - public static final String ACCEPT_ELABORATED = "ACCEPT_ELABORATED"; //$NON-NLS-1$ - public static final String ACCEPT_ABSTRACT_TYPESPEC = "ACCEPT_ABSTRACT_TYPESPEC"; //$NON-NLS-1$ - public static final String ACCEPT_METHOD = "ACCEPT_METHOD"; //$NON-NLS-1$ - public static final String ACCEPT_FIELD = "ACCEPT_FIELD"; //$NON-NLS-1$ - public static final String ACCEPT_REFERENCE = "ACCEPT_REFERENCE"; //$NON-NLS-1$ - public static final String ACCEPT_FRIEND = "ACCEPT_FRIEND"; //$NON-NLS-1$ - public static final String ENTER_FUNCTION = "ENTER_FUNCTION"; //$NON-NLS-1$ - public static final String ENTER_CODE_BLOCK = "ENTER_CODE_BLOCK"; //$NON-NLS-1$ - public static final String ENTER_COMPILATION_UNIT = "ENTER_COMPILATION_UNIT"; //$NON-NLS-1$ - public static final String ENTER_INCLUSION = "ENTER_INCLUSION"; //$NON-NLS-1$ - public static final String ENTER_NAMESPACE = "ENTER_NAMESPACE"; //$NON-NLS-1$ - public static final String ENTER_CLASS_SPEC = "ENTER_CLASS_SPEC"; //$NON-NLS-1$ - public static final String ENTER_LINKAGE = "ENTER_LINKAGE"; //$NON-NLS-1$ - public static final String ENTER_TEMPLATE_DECL = "ENTER_TEMPLATE_DECL"; //$NON-NLS-1$ - public static final String ENTER_TEMPLATE_SPEC = "ENTER_TEMPLATE_SPEC"; //$NON-NLS-1$ - public static final String ENTER_TEMPLATE_INSTANCE = "ENTER_TEMPLATE_INSTANCE"; //$NON-NLS-1$ - public static final String ENTER_METHOD = "ENTER_METHOD"; //$NON-NLS-1$ - public static final String EXIT_FUNCTION = "EXIT_FUNCTION"; //$NON-NLS-1$ - public static final String EXIT_CODE_BLOCK = "EXIT_CODE_BLOCK"; //$NON-NLS-1$ - public static final String EXIT_METHOD = "EXIT_METHOD"; //$NON-NLS-1$ - public static final String EXIT_TEMPLATE_DECL = "EXIT_TEMPLATE_DECL"; //$NON-NLS-1$ - public static final String EXIT_TEMPLATE_SPEC = "EXIT_TEMPLATE_SPEC"; //$NON-NLS-1$ - public static final String EXIT_TEMPLATE_INSTANCE = "EXIT_TEMPLATE_INSTANCE"; //$NON-NLS-1$ - public static final String EXIT_LINKAGE = "EXIT_LINKAGE"; //$NON-NLS-1$ - public static final String EXIT_CLASS = "EXIT_CLASS"; //$NON-NLS-1$ - public static final String EXIT_NAMESPACE = "EXIT_NAMESPACE"; //$NON-NLS-1$ - public static final String EXIT_INCLUSION = "EXIT_INCLUSION"; //$NON-NLS-1$ - public static final String EXIT_COMPILATION_UNIT = "EXIT_COMPILATION_UNIT"; //$NON-NLS-1$ - - - public boolean acceptProblem( IProblem problem ) { - callbacks.add( ACCEPT_PROBLEM ); - return false; - } - public void acceptMacro( IASTMacro macro ) { callbacks.add( ACCEPT_MACRO ); } - public void acceptVariable( IASTVariable variable ) { callbacks.add( ACCEPT_VARIABLE ); } - public void acceptFunctionDeclaration( IASTFunction function ) { callbacks.add( ACCEPT_FUNCTION_DECL); } - public void acceptUsingDirective( IASTUsingDirective usageDirective ) { callbacks.add( ACCEPT_USING_DIRECTIVE ); } - public void acceptUsingDeclaration( IASTUsingDeclaration usageDeclaration ) { callbacks.add( ACCEPT_USING_DECL ); } - public void acceptASMDefinition( IASTASMDefinition asmDefinition ) { callbacks.add( ACCEPT_ASM_DEF ); } - public void acceptTypedefDeclaration( IASTTypedefDeclaration typedef ) { callbacks.add( ACCEPT_TYPEDEF ); } - public void acceptEnumerationSpecifier( IASTEnumerationSpecifier enumeration ) { callbacks.add( ACCEPT_ENUMERATION); } - public void acceptElaboratedForewardDeclaration( IASTElaboratedTypeSpecifier elaboratedType ) { callbacks.add( ACCEPT_ELABORATED ); } - public void acceptAbstractTypeSpecDeclaration( IASTAbstractTypeSpecifierDeclaration abstractDeclaration ) { callbacks.add( ACCEPT_ABSTRACT_TYPESPEC); } - public void enterFunctionBody( IASTFunction function ) { callbacks.add( ENTER_FUNCTION ); } - public void exitFunctionBody( IASTFunction function ) { callbacks.add( EXIT_FUNCTION ); } - public void enterCodeBlock( IASTCodeScope scope ) { callbacks.add( ENTER_CODE_BLOCK ); } - public void exitCodeBlock( IASTCodeScope scope ) { callbacks.add( EXIT_CODE_BLOCK ); } - public void enterInclusion( IASTInclusion inclusion ) { callbacks.add( ENTER_INCLUSION ); } - public void enterNamespaceDefinition( IASTNamespaceDefinition namespaceDefinition ) { callbacks.add( ENTER_NAMESPACE ); } - public void enterClassSpecifier( IASTClassSpecifier classSpecification ) { callbacks.add( ENTER_CLASS_SPEC ); } - public void enterLinkageSpecification( IASTLinkageSpecification linkageSpec ) { callbacks.add( ENTER_LINKAGE ); } - public void enterTemplateDeclaration( IASTTemplateDeclaration declaration ) { callbacks.add( ENTER_TEMPLATE_DECL ); } - public void enterTemplateSpecialization( IASTTemplateSpecialization specialization ) { callbacks.add( ENTER_TEMPLATE_SPEC ); } - public void enterTemplateInstantiation( IASTTemplateInstantiation instantiation ) { callbacks.add( ENTER_TEMPLATE_INSTANCE ); } - public void acceptMethodDeclaration( IASTMethod method ) { callbacks.add( ACCEPT_METHOD ); } - public void enterMethodBody( IASTMethod method ) { callbacks.add( ENTER_METHOD ); } - public void exitMethodBody( IASTMethod method ) { callbacks.add( EXIT_METHOD ); } - public void acceptField( IASTField field ) { callbacks.add( ACCEPT_FIELD ); } - public void acceptClassReference( IASTClassReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptTypedefReference( IASTTypedefReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptNamespaceReference( IASTNamespaceReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptEnumerationReference( IASTEnumerationReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptVariableReference( IASTVariableReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptFunctionReference( IASTFunctionReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptFieldReference( IASTFieldReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptMethodReference( IASTMethodReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptEnumeratorReference( IASTEnumeratorReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptParameterReference( IASTParameterReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptTemplateParameterReference( IASTTemplateParameterReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } - public void acceptFriendDeclaration( IASTDeclaration declaration ) { callbacks.add( ACCEPT_FRIEND ); } - public void exitTemplateDeclaration( IASTTemplateDeclaration declaration ) { callbacks.add( EXIT_TEMPLATE_DECL); } - public void exitTemplateSpecialization( IASTTemplateSpecialization specialization ) { callbacks.add( EXIT_TEMPLATE_SPEC ); } - public void exitTemplateExplicitInstantiation( IASTTemplateInstantiation instantiation ) { callbacks.add( EXIT_TEMPLATE_INSTANCE ); } - public void exitLinkageSpecification( IASTLinkageSpecification linkageSpec ) { callbacks.add( ACCEPT_MACRO ); } - public void exitClassSpecifier( IASTClassSpecifier classSpecification ) { callbacks.add( EXIT_CLASS ); } - public void exitNamespaceDefinition( IASTNamespaceDefinition namespaceDefinition ) { callbacks.add( EXIT_NAMESPACE); } - public void exitInclusion( IASTInclusion inclusion ) { callbacks.add( EXIT_INCLUSION ); } - public void exitCompilationUnit( IASTCompilationUnit compilationUnit ) { callbacks.add( EXIT_COMPILATION_UNIT ); } - public void enterCompilationUnit( IASTCompilationUnit compilationUnit ) - { - callbacks.add( ENTER_COMPILATION_UNIT ); - compUnit = compilationUnit; - } - public CodeReader createReader( String finalPath, Iterator workingCopies ) { - return ParserUtil.createReader(finalPath,workingCopies); - } - - } - public CallbackTracker callback; - protected IASTScope parse( IFile code, List callbacks ) throws Exception - { - return parse( code, callbacks, ParserLanguage.CPP ); - } - - protected IASTScope parse(IFile code, List callbackList, ParserLanguage language) throws Exception - { - callback = new CallbackTracker( callbackList ); - InputStream stream = code.getContents(); - IParser parser = ParserFactory.createParser( - ParserFactory.createScanner( new CodeReader( code.getLocation().toOSString(), stream ), new ScannerInfo(), //$NON-NLS-1$ - ParserMode.COMPLETE_PARSE, language, callback, new NullLogService(), null ), callback, ParserMode.COMPLETE_PARSE, language, null - ); - stream.close(); - boolean parseResult = parser.parse(); - // throw exception if there are generated IProblems - if( !parseResult ) throw new ParserException( "FAILURE"); //$NON-NLS-1$ - if( parseResult ) - { - assertTrue( ((Parser)parser).validateCaches()); - } - return callback.getCompilationUnit(); - } - + public void testBug72219() throws Exception { String foo = "int FOO;"; //$NON-NLS-1$ String code = "#include \"foo.h\" \n int bar;"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FileBasePluginTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FileBasePluginTest.java new file mode 100644 index 00000000000..b98f8774946 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FileBasePluginTest.java @@ -0,0 +1,336 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Sept 28, 2004 + */ +package org.eclipse.cdt.core.parser.tests; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.List; + +import junit.framework.TestCase; + + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.IParser; +import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; +import org.eclipse.cdt.core.parser.NullLogService; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ParserUtil; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.ast.IASTASMDefinition; +import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTClassReference; +import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTCodeScope; +import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit; +import org.eclipse.cdt.core.parser.ast.IASTDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTEnumerationReference; +import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.parser.ast.IASTEnumeratorReference; +import org.eclipse.cdt.core.parser.ast.IASTField; +import org.eclipse.cdt.core.parser.ast.IASTFieldReference; +import org.eclipse.cdt.core.parser.ast.IASTFunction; +import org.eclipse.cdt.core.parser.ast.IASTFunctionReference; +import org.eclipse.cdt.core.parser.ast.IASTInclusion; +import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; +import org.eclipse.cdt.core.parser.ast.IASTMacro; +import org.eclipse.cdt.core.parser.ast.IASTMethod; +import org.eclipse.cdt.core.parser.ast.IASTMethodReference; +import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; +import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference; +import org.eclipse.cdt.core.parser.ast.IASTParameterReference; +import org.eclipse.cdt.core.parser.ast.IASTScope; +import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation; +import org.eclipse.cdt.core.parser.ast.IASTTemplateParameterReference; +import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization; +import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTTypedefReference; +import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; +import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; +import org.eclipse.cdt.core.parser.ast.IASTVariable; +import org.eclipse.cdt.core.parser.ast.IASTVariableReference; + +import org.eclipse.cdt.internal.core.parser.Parser; +import org.eclipse.cdt.internal.core.parser.ParserException; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.testplugin.CProjectHelper; +import org.eclipse.cdt.testplugin.CTestPlugin; +import org.eclipse.cdt.testplugin.FileManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.SaveAsDialog; + +/** + * @author dsteffle + */ +public class FileBasePluginTest extends TestCase { + static NullProgressMonitor monitor; + static IWorkspace workspace; + static IProject project; + static FileManager fileManager; + static int numProjects = 0; + static Class className; + static ICProject cPrj; + + private void initialize(Class aClassName){ + if( CCorePlugin.getDefault() != null && CCorePlugin.getDefault().getCoreModel() != null){ + (CCorePlugin.getDefault().getCoreModel().getIndexManager()).reset(); + monitor = new NullProgressMonitor(); + + workspace = ResourcesPlugin.getWorkspace(); + + try { + cPrj = CProjectHelper.createCCProject("ParserTestProject", "bin"); //$NON-NLS-1$ //$NON-NLS-2$ + + project = cPrj.getProject(); + project.setSessionProperty(IndexManager.activationKey,new Boolean(false)); + + // ugly + if (className == null || !className.equals(aClassName)) { + className = aClassName; + numProjects++; + } + } catch ( CoreException e ) { + /*boo*/ + } + if (project == null) + throw new NullPointerException("Unable to create project"); //$NON-NLS-1$ + + //Create file manager + fileManager = new FileManager(); + } + } + + public FileBasePluginTest(String name, Class className) + { + super(name); + initialize(className); + } + + public void cleanupProject() throws Exception { + numProjects--; + + try{ + if (numProjects == 0) { + project.delete( true, false, monitor ); + project = null; + } + } catch( Throwable e ){ + /*boo*/ + } + } + + protected void tearDown() throws Exception { + if( project == null || !project.exists() ) + return; + + IResource [] members = project.members(); + for( int i = 0; i < members.length; i++ ){ + if( members[i].getName().equals( ".project" ) || members[i].getName().equals( ".cdtproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ + continue; + try{ + members[i].delete( false, monitor ); + } catch( Throwable e ){ + /*boo*/ + } + } + } + + // below can be used to work with large files (too large for memory) +// protected IFile importFile(String fileName) throws Exception { +// IFile file = cPrj.getProject().getFile(fileName); +// if (!file.exists()) { +// try{ +// FileInputStream fileIn = new FileInputStream( +// CTestPlugin.getDefault().getFileInPlugin(new Path("resources/parser/" + fileName))); +// file.create(fileIn,false, monitor); +// } catch (CoreException e) { +// e.printStackTrace(); +// } catch (FileNotFoundException e) { +// e.printStackTrace(); +// } +// } +// +// return file; +// } + + protected IFile importFile(String fileName, String contents ) throws Exception{ + //Obtain file handle + IFile file = project.getProject().getFile(fileName); + + InputStream stream = new ByteArrayInputStream( contents.getBytes() ); + //Create file input stream + if( file.exists() ) + file.setContents( stream, false, false, monitor ); + else + file.create( stream, false, monitor ); + + fileManager.addFile(file); + + return file; + } + + public static class CallbackTracker implements ISourceElementRequestor{ + private List callbacks; + private IASTScope compUnit; + public CallbackTracker( List callbacks ){ + this.callbacks = callbacks; + } + + public IASTScope getCompilationUnit() + { + return compUnit; + } + public static final String ACCEPT_PROBLEM = "ACCEPT_PROBLEM"; //$NON-NLS-1$ + public static final String ACCEPT_MACRO = "ACCEPT_MACRO"; //$NON-NLS-1$ + public static final String ACCEPT_VARIABLE = "ACCEPT_VARIABLE"; //$NON-NLS-1$ + public static final String ACCEPT_FUNCTION_DECL = "ACCEPT_FUNCTION_DECL"; //$NON-NLS-1$ + public static final String ACCEPT_USING_DIRECTIVE = "ACCEPT_USING_DIRECTIVE"; //$NON-NLS-1$ + public static final String ACCEPT_USING_DECL = "ACCEPT_USING_DECL"; //$NON-NLS-1$ + public static final String ACCEPT_ASM_DEF = "ACCEPT_ASM_DEF"; //$NON-NLS-1$ + public static final String ACCEPT_TYPEDEF = "ACCEPT_TYPEDEF"; //$NON-NLS-1$ + public static final String ACCEPT_ENUMERATION = "ACCEPT_ENUMERATION"; //$NON-NLS-1$ + public static final String ACCEPT_ELABORATED = "ACCEPT_ELABORATED"; //$NON-NLS-1$ + public static final String ACCEPT_ABSTRACT_TYPESPEC = "ACCEPT_ABSTRACT_TYPESPEC"; //$NON-NLS-1$ + public static final String ACCEPT_METHOD = "ACCEPT_METHOD"; //$NON-NLS-1$ + public static final String ACCEPT_FIELD = "ACCEPT_FIELD"; //$NON-NLS-1$ + public static final String ACCEPT_REFERENCE = "ACCEPT_REFERENCE"; //$NON-NLS-1$ + public static final String ACCEPT_FRIEND = "ACCEPT_FRIEND"; //$NON-NLS-1$ + public static final String ENTER_FUNCTION = "ENTER_FUNCTION"; //$NON-NLS-1$ + public static final String ENTER_CODE_BLOCK = "ENTER_CODE_BLOCK"; //$NON-NLS-1$ + public static final String ENTER_COMPILATION_UNIT = "ENTER_COMPILATION_UNIT"; //$NON-NLS-1$ + public static final String ENTER_INCLUSION = "ENTER_INCLUSION"; //$NON-NLS-1$ + public static final String ENTER_NAMESPACE = "ENTER_NAMESPACE"; //$NON-NLS-1$ + public static final String ENTER_CLASS_SPEC = "ENTER_CLASS_SPEC"; //$NON-NLS-1$ + public static final String ENTER_LINKAGE = "ENTER_LINKAGE"; //$NON-NLS-1$ + public static final String ENTER_TEMPLATE_DECL = "ENTER_TEMPLATE_DECL"; //$NON-NLS-1$ + public static final String ENTER_TEMPLATE_SPEC = "ENTER_TEMPLATE_SPEC"; //$NON-NLS-1$ + public static final String ENTER_TEMPLATE_INSTANCE = "ENTER_TEMPLATE_INSTANCE"; //$NON-NLS-1$ + public static final String ENTER_METHOD = "ENTER_METHOD"; //$NON-NLS-1$ + public static final String EXIT_FUNCTION = "EXIT_FUNCTION"; //$NON-NLS-1$ + public static final String EXIT_CODE_BLOCK = "EXIT_CODE_BLOCK"; //$NON-NLS-1$ + public static final String EXIT_METHOD = "EXIT_METHOD"; //$NON-NLS-1$ + public static final String EXIT_TEMPLATE_DECL = "EXIT_TEMPLATE_DECL"; //$NON-NLS-1$ + public static final String EXIT_TEMPLATE_SPEC = "EXIT_TEMPLATE_SPEC"; //$NON-NLS-1$ + public static final String EXIT_TEMPLATE_INSTANCE = "EXIT_TEMPLATE_INSTANCE"; //$NON-NLS-1$ + public static final String EXIT_LINKAGE = "EXIT_LINKAGE"; //$NON-NLS-1$ + public static final String EXIT_CLASS = "EXIT_CLASS"; //$NON-NLS-1$ + public static final String EXIT_NAMESPACE = "EXIT_NAMESPACE"; //$NON-NLS-1$ + public static final String EXIT_INCLUSION = "EXIT_INCLUSION"; //$NON-NLS-1$ + public static final String EXIT_COMPILATION_UNIT = "EXIT_COMPILATION_UNIT"; //$NON-NLS-1$ + + + public boolean acceptProblem( IProblem problem ) { + callbacks.add( ACCEPT_PROBLEM ); + return false; + } + public void acceptMacro( IASTMacro macro ) { callbacks.add( ACCEPT_MACRO ); } + public void acceptVariable( IASTVariable variable ) { callbacks.add( ACCEPT_VARIABLE ); } + public void acceptFunctionDeclaration( IASTFunction function ) { callbacks.add( ACCEPT_FUNCTION_DECL); } + public void acceptUsingDirective( IASTUsingDirective usageDirective ) { callbacks.add( ACCEPT_USING_DIRECTIVE ); } + public void acceptUsingDeclaration( IASTUsingDeclaration usageDeclaration ) { callbacks.add( ACCEPT_USING_DECL ); } + public void acceptASMDefinition( IASTASMDefinition asmDefinition ) { callbacks.add( ACCEPT_ASM_DEF ); } + public void acceptTypedefDeclaration( IASTTypedefDeclaration typedef ) { callbacks.add( ACCEPT_TYPEDEF ); } + public void acceptEnumerationSpecifier( IASTEnumerationSpecifier enumeration ) { callbacks.add( ACCEPT_ENUMERATION); } + public void acceptElaboratedForewardDeclaration( IASTElaboratedTypeSpecifier elaboratedType ) { callbacks.add( ACCEPT_ELABORATED ); } + public void acceptAbstractTypeSpecDeclaration( IASTAbstractTypeSpecifierDeclaration abstractDeclaration ) { callbacks.add( ACCEPT_ABSTRACT_TYPESPEC); } + public void enterFunctionBody( IASTFunction function ) { callbacks.add( ENTER_FUNCTION ); } + public void exitFunctionBody( IASTFunction function ) { callbacks.add( EXIT_FUNCTION ); } + public void enterCodeBlock( IASTCodeScope scope ) { callbacks.add( ENTER_CODE_BLOCK ); } + public void exitCodeBlock( IASTCodeScope scope ) { callbacks.add( EXIT_CODE_BLOCK ); } + public void enterInclusion( IASTInclusion inclusion ) { callbacks.add( ENTER_INCLUSION ); } + public void enterNamespaceDefinition( IASTNamespaceDefinition namespaceDefinition ) { callbacks.add( ENTER_NAMESPACE ); } + public void enterClassSpecifier( IASTClassSpecifier classSpecification ) { callbacks.add( ENTER_CLASS_SPEC ); } + public void enterLinkageSpecification( IASTLinkageSpecification linkageSpec ) { callbacks.add( ENTER_LINKAGE ); } + public void enterTemplateDeclaration( IASTTemplateDeclaration declaration ) { callbacks.add( ENTER_TEMPLATE_DECL ); } + public void enterTemplateSpecialization( IASTTemplateSpecialization specialization ) { callbacks.add( ENTER_TEMPLATE_SPEC ); } + public void enterTemplateInstantiation( IASTTemplateInstantiation instantiation ) { callbacks.add( ENTER_TEMPLATE_INSTANCE ); } + public void acceptMethodDeclaration( IASTMethod method ) { callbacks.add( ACCEPT_METHOD ); } + public void enterMethodBody( IASTMethod method ) { callbacks.add( ENTER_METHOD ); } + public void exitMethodBody( IASTMethod method ) { callbacks.add( EXIT_METHOD ); } + public void acceptField( IASTField field ) { callbacks.add( ACCEPT_FIELD ); } + public void acceptClassReference( IASTClassReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptTypedefReference( IASTTypedefReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptNamespaceReference( IASTNamespaceReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptEnumerationReference( IASTEnumerationReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptVariableReference( IASTVariableReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptFunctionReference( IASTFunctionReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptFieldReference( IASTFieldReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptMethodReference( IASTMethodReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptEnumeratorReference( IASTEnumeratorReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptParameterReference( IASTParameterReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptTemplateParameterReference( IASTTemplateParameterReference reference ) { callbacks.add( ACCEPT_REFERENCE ); } + public void acceptFriendDeclaration( IASTDeclaration declaration ) { callbacks.add( ACCEPT_FRIEND ); } + public void exitTemplateDeclaration( IASTTemplateDeclaration declaration ) { callbacks.add( EXIT_TEMPLATE_DECL); } + public void exitTemplateSpecialization( IASTTemplateSpecialization specialization ) { callbacks.add( EXIT_TEMPLATE_SPEC ); } + public void exitTemplateExplicitInstantiation( IASTTemplateInstantiation instantiation ) { callbacks.add( EXIT_TEMPLATE_INSTANCE ); } + public void exitLinkageSpecification( IASTLinkageSpecification linkageSpec ) { callbacks.add( ACCEPT_MACRO ); } + public void exitClassSpecifier( IASTClassSpecifier classSpecification ) { callbacks.add( EXIT_CLASS ); } + public void exitNamespaceDefinition( IASTNamespaceDefinition namespaceDefinition ) { callbacks.add( EXIT_NAMESPACE); } + public void exitInclusion( IASTInclusion inclusion ) { callbacks.add( EXIT_INCLUSION ); } + public void exitCompilationUnit( IASTCompilationUnit compilationUnit ) { callbacks.add( EXIT_COMPILATION_UNIT ); } + public void enterCompilationUnit( IASTCompilationUnit compilationUnit ) + { + callbacks.add( ENTER_COMPILATION_UNIT ); + compUnit = compilationUnit; + } + public CodeReader createReader( String finalPath, Iterator workingCopies ) { + return ParserUtil.createReader(finalPath,workingCopies); + } + + } + public CallbackTracker callback; + protected IASTScope parse( IFile code, List callbacks ) throws Exception + { + return parse( code, callbacks, ParserLanguage.CPP ); + } + + protected IASTScope parse(IFile code, List callbackList, ParserLanguage language) throws Exception + { + callback = new CallbackTracker( callbackList ); + InputStream stream = code.getContents(); + IParser parser = ParserFactory.createParser( + ParserFactory.createScanner( new CodeReader( code.getLocation().toOSString(), stream ), new ScannerInfo(), //$NON-NLS-1$ + ParserMode.COMPLETE_PARSE, language, callback, new NullLogService(), null ), callback, ParserMode.COMPLETE_PARSE, language, null + ); + stream.close(); + boolean parseResult = parser.parse(); + // throw exception if there are generated IProblems + if( !parseResult ) throw new ParserException( "FAILURE"); //$NON-NLS-1$ + if( parseResult ) + { + assertTrue( ((Parser)parser).validateCaches()); + } + return callback.getCompilationUnit(); + } + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java index 8daf96c2d4b..6c3e998b7f1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java @@ -48,6 +48,7 @@ public class ParserTestSuite extends TestCase { suite.addTestSuite( StructuralParseTest.class ); suite.addTestSuite( ObjectMapTest.class ); suite.addTest( CompleteParsePluginTest.suite() ); + suite.addTest( ScannerParserLoopTest.suite() ); suite.addTest( GCCParserExtensionTestSuite.suite() ); return suite; } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerParserLoopTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerParserLoopTest.java new file mode 100644 index 00000000000..47fec8a2621 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerParserLoopTest.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Sept 30, 2004 + */ +package org.eclipse.cdt.core.parser.tests; + +import java.io.StringWriter; +import java.io.Writer; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.eclipse.cdt.core.parser.CodeReader; +import org.eclipse.cdt.core.parser.IParser; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; +import org.eclipse.cdt.core.parser.NullLogService; +import org.eclipse.cdt.core.parser.NullSourceElementRequestor; +import org.eclipse.cdt.core.parser.ParseError; +import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.core.resources.IFile; +import org.eclipse.cdt.core.parser.ast.IASTMacro; +import org.eclipse.cdt.core.parser.ast.IASTVariable; + +/** + * @author dsteffle + */ +public class ScannerParserLoopTest extends FileBasePluginTest { + private static final int NUMBER_ITERATIONS = 30000; + + public ScannerParserLoopTest(String name) { + super(name, ScannerParserLoopTest.class); + } + + public static Test suite() { + TestSuite suite = new TestSuite(ScannerParserLoopTest.class); + suite.addTest(new ScannerParserLoopTest("cleanupProject")); //$NON-NLS-1$ + return suite; + } + + // test scanner cancel() + public void testBug72611A() throws Exception { + Writer writer = new StringWriter(); + + for (int i = 0; i < NUMBER_ITERATIONS; i++) { + writer.write("#define A"); + writer.write(String.valueOf(i)); + writer.write(" B"); + writer.write(String.valueOf(i)); + writer.write("\n"); + writer.write("#define B"); + writer.write(String.valueOf(i)); + writer.write(" C"); + writer.write(String.valueOf(i)); + writer.write("\n"); + writer.write("#define C"); + writer.write(String.valueOf(i)); + writer.write(" D"); + writer.write(String.valueOf(i)); + writer.write("\n"); + } + + runCancelTest(writer); + } + + // test parser cancel() + public void testBug72611B() throws Exception { + Writer writer = new StringWriter(); + + for (int i = 0; i < NUMBER_ITERATIONS; i++) { + writer.write("int a"); + writer.write(String.valueOf(i)); + writer.write("; // comment\n"); + } + + runCancelTest(writer); + } + + private void runCancelTest(Writer writer) throws Exception { + IFile file = importFile("code.cpp", writer.toString()); //$NON-NLS-1$ + + try { + TimeoutCallback callback = new TimeoutCallback(); + IParser parser = ParserFactory.createParser(ParserFactory + .createScanner(new CodeReader(file.getRawLocation() + .toString()), new ScannerInfo(), //$NON-NLS-1$ + ParserMode.COMPLETE_PARSE, ParserLanguage.CPP, + callback, new NullLogService(), null), callback, + ParserMode.COMPLETE_PARSE, ParserLanguage.CPP, null); + + callback.setParser(parser); + parser.parse(); + + assertTrue(false); // fail if parse succeeds before being cancelled + } catch (ParseError pe) { // expected + assertEquals(pe.getErrorKind(), + ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); + } + } + + private static class TimeoutCallback extends NullSourceElementRequestor + implements ISourceElementRequestor { + private IParser parser; + private boolean timerStarted = false; + + public void setParser(IParser parser) { + this.parser = parser; + } + + public void acceptMacro(IASTMacro macro) { + parser.cancel(); + } + + public void acceptVariable(IASTVariable variable) { + parser.cancel(); + } + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java index afd87ca37d3..a5b219c06bc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java @@ -36,5 +36,5 @@ public interface IScanner { public int getCount(); public boolean isOnTopContext(); public CharArrayObjectMap getRealDefinitions(); - + public void cancel(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java index e0abeb8de32..8e2a32fd929 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java @@ -6275,6 +6275,7 @@ public class Parser implements IParserData, IParser */ public synchronized void cancel() { isCancelled = true; + scanner.cancel(); } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java index da4fd282424..0318d675168 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/Scanner2.java @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.KeywordSetKey; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.OffsetLimitReachedException; +import org.eclipse.cdt.core.parser.ParseError; import org.eclipse.cdt.core.parser.ParserFactory; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserMode; @@ -380,8 +381,13 @@ public class Scanner2 implements IScanner, IScannerData { private static final String EMPTY_STRING = ""; //$NON-NLS-1$ private static final char[] EMPTY_STRING_CHAR_ARRAY = new char[0]; + private boolean isCancelled = false; - + public synchronized void cancel() { + isCancelled = true; + int index = bufferStackPos < 0 ? 0 : bufferStackPos; + bufferPos[index] = bufferLimit[index]; + } /* (non-Javadoc) * @see org.eclipse.cdt.core.parser.IScanner#nextToken() @@ -397,6 +403,8 @@ public class Scanner2 implements IScanner, IScannerData { { if( e instanceof OffsetLimitReachedException ) throw (OffsetLimitReachedException) e; + if( e instanceof ArrayIndexOutOfBoundsException && isCancelled ) + throw new ParseError( ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); exception = true; errorHandle(); @@ -413,6 +421,9 @@ public class Scanner2 implements IScanner, IScannerData { if (finished) { + if (isCancelled == true) + throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); + if( offsetBoundary == -1 ) throw EOF; throwOLRE(); @@ -491,7 +502,9 @@ public class Scanner2 implements IScanner, IScannerData { ++count; contextLoop: while (bufferStackPos >= 0) { - + if (isCancelled == true) + throw new ParseError(ParseError.ParseErrorKind.TIMEOUT_OR_CANCELLED); + // Find the first thing we would care about skipOverWhiteSpace();