/* * Copyright 2009-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.jdt.groovy.model; import java.util.HashMap; import java.util.Map; import org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.core.CompilationUnitProblemFinder; import org.eclipse.jdt.internal.core.JavaElementDelta; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation; /** * Overrides super type with a custom {@link #makeConsistent(org.eclipse.jdt.internal.core.CompilationUnit)} method. * * Need to ensure that the {@link ModuleNode} is cached in the {@link ModuleNodeMapper} after a call to make consistent. */ public class GroovyReconcileWorkingCopyOperation extends ReconcileWorkingCopyOperation { WorkingCopyOwner workingCopyOwner; public GroovyReconcileWorkingCopyOperation(IJavaElement workingCopy, int astLevel, int reconcileFlags, WorkingCopyOwner workingCopyOwner) { super(workingCopy, astLevel, reconcileFlags, workingCopyOwner); this.workingCopyOwner = workingCopyOwner; } // Copied from Super /* * Makes the given working copy consistent, computes the delta and computes an AST if needed. Returns the AST. */ public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(org.eclipse.jdt.internal.core.CompilationUnit workingCopy) throws JavaModelException { if (!workingCopy.isConsistent()) { // make working copy consistent if (this.problems == null) this.problems = new HashMap<String, CategorizedProblem[]>(); this.resolveBindings = this.requestorIsActive; this.ast = workingCopy.makeConsistent(this.astLevel, this.resolveBindings, this.reconcileFlags, this.problems, this.progressMonitor); this.deltaBuilder.buildDeltas(); if (this.ast != null && this.deltaBuilder.delta != null) this.deltaBuilder.delta.changedAST(this.ast); return this.ast; } if (this.ast != null) return this.ast; // no need to recompute AST if known already CompilationUnitDeclaration unit = null; try { JavaModelManager.getJavaModelManager().abortOnMissingSource.set(Boolean.TRUE); org.eclipse.jdt.internal.core.CompilationUnit source = workingCopy.cloneCachingContents(); // find problems if needed if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject()) && (this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0) { this.resolveBindings = this.requestorIsActive; if (this.problems == null) this.problems = new HashMap<String, CategorizedProblem[]>(); unit = CompilationUnitProblemFinder.process( source, this.workingCopyOwner, this.problems, this.astLevel != ICompilationUnit.NO_AST, // creating AST if level is not NO_AST this.reconcileFlags, this.progressMonitor); // GROOVY cache the ModuleNode in the ModuleNodeMapper if (unit instanceof GroovyCompilationUnitDeclaration && !(workingCopy instanceof GroovyClassFileWorkingCopy)) { ModuleNodeMapper.getInstance().maybeCacheModuleNode(workingCopy.getPerWorkingCopyInfo(), (GroovyCompilationUnitDeclaration) unit); } // GROOVY end if (this.progressMonitor != null) this.progressMonitor.worked(1); } // create AST if needed if (this.astLevel != ICompilationUnit.NO_AST && unit != null/*unit is null if working copy is consistent && (problem detection not forced || non-Java project) -> don't create AST as per API*/) { Map<String, String> options = workingCopy.getJavaProject().getOptions(true); // convert AST this.ast = AST.convertCompilationUnit( this.astLevel, unit, options, this.resolveBindings, source, this.reconcileFlags, this.progressMonitor); if (this.ast != null) { if (this.deltaBuilder.delta == null) { this.deltaBuilder.delta = new JavaElementDelta(workingCopy); } this.deltaBuilder.delta.changedAST(this.ast); } if (this.progressMonitor != null) this.progressMonitor.worked(1); } } catch (JavaModelException e) { if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject())) throw e; // else JavaProject has lost its nature (or most likely was closed/deleted) while reconciling -> ignore // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100919) } finally { JavaModelManager.getJavaModelManager().abortOnMissingSource.set(null); if (unit != null) { unit.cleanUp(); } } return this.ast; } }