1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

AST concurrency issue in rename refactoring.

This commit is contained in:
Sergey Prigogin 2011-04-13 02:33:39 +00:00
parent c130243446
commit 987feb04be
2 changed files with 57 additions and 31 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2005, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -23,16 +23,16 @@ import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.services.IDisposable;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -101,7 +101,6 @@ import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
@ -111,7 +110,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.corext.util.CModelUtil;
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
@ -119,12 +117,19 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
/**
* Used for refactoring to cache the IASTTranslationUnits.
* Contains a collection of methods operating on ASTNodes.
* The object has to be disposed of after use.
*/
public class ASTManager {
public final static int TRUE= 1;
public class ASTManager implements IDisposable {
private static final int PARSE_MODE = ITranslationUnit.AST_SKIP_ALL_HEADERS
| ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT
| ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS
| ITranslationUnit.AST_PARSE_INACTIVE_CODE;
public final static int TRUE= 1;
public final static int FALSE= 0;
public final static int UNKNOWN= -1;
private IASTTranslationUnit fSharedAST;
private Map<IFile, IASTTranslationUnit> fTranslationUnits= new HashMap<IFile, IASTTranslationUnit>();
private HashSet<String> fProblemUnits= new HashSet<String>();
private CRefactoringArgument fArgument;
@ -132,6 +137,7 @@ public class ASTManager {
private String fRenameTo;
private HashMap<IBinding, Integer> fKnownBindings;
private HashSet<IBinding> fConflictingBinding;
private boolean fDisposed;
public static String nth_of_m(int n, int m) {
StringBuilder nofm= new StringBuilder();
@ -782,7 +788,25 @@ public class ASTManager {
fArgument= arg;
}
void analyzeArgument(IIndex index, IProgressMonitor pm, RefactoringStatus status) {
/**
* @see IDisposable#dispose()
*/
public void dispose() {
Assert.isTrue(!fDisposed, "ASTManager.dispose() called more than once"); //$NON-NLS-1$
fDisposed = true;
if (fSharedAST != null) {
ASTProvider.getASTProvider().releaseSharedAST(fSharedAST);
}
}
@Override
protected void finalize() throws Throwable {
if (!fDisposed)
CUIPlugin.logError("ASTManager was not disposed"); //$NON-NLS-1$
super.finalize();
}
void analyzeArgument(IIndex index, IProgressMonitor pm, RefactoringStatus status) {
if (fArgument == null) {
return;
}
@ -881,29 +905,28 @@ public class ASTManager {
ICElement celem= CoreModel.getDefault().create(sourceFile);
if (celem instanceof ITranslationUnit) {
ITranslationUnit tu= CModelUtil.toWorkingCopy((ITranslationUnit) celem);
// Try to get a shared AST before creating our own.
final IASTTranslationUnit[] ast_holder = new IASTTranslationUnit[1];
ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_IF_OPEN, null, new ASTRunnable() {
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
// Leaking of AST outside of runOnAST method is a dangerous, but it does not cause
// harm here since the index remains locked for the life time of the AST.
ast_holder[0] = ast;
return Status.OK_STATUS;
}
});
ast = ast_holder[0];
if (ast == null) {
int options= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT |
ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
try {
ast= tu.getAST(index, options);
} catch (CoreException e) {
status.addError(e.getMessage());
}
if (cacheit) {
fTranslationUnits.put(sourceFile, ast);
}
}
if (fSharedAST != null && tu.equals(fSharedAST.getOriginatingTranslationUnit())) {
ast = fSharedAST;
} else {
// Try to get a shared AST before creating our own.
ast = ASTProvider.getASTProvider().acquireSharedAST(tu, index,
ASTProvider.WAIT_ACTIVE_ONLY, null);
if (ast == null) {
try {
ast= tu.getAST(index, PARSE_MODE);
} catch (CoreException e) {
status.addError(e.getMessage());
}
if (cacheit) {
fTranslationUnits.put(sourceFile, ast);
}
} else {
if (fSharedAST != null) {
ASTProvider.getASTProvider().releaseSharedAST(fSharedAST);
}
fSharedAST = ast;
}
}
}
}
return ast;

View file

@ -288,6 +288,9 @@ public class CRenameProcessor extends RenameProcessor {
}
public void unlockIndex() {
if (fAstManager != null) {
fAstManager.dispose();
}
if (fIndex != null) {
fIndex.releaseReadLock();
}