| /*=============================================================================# |
| # Copyright (c) 2015, 2019 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.r.console.core; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| import org.eclipse.statet.jcommons.collections.IntArrayList; |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| import org.eclipse.statet.jcommons.collections.IntList; |
| import org.eclipse.statet.jcommons.status.ErrorStatus; |
| import org.eclipse.statet.jcommons.status.ProgressMonitor; |
| import org.eclipse.statet.jcommons.status.StatusException; |
| import org.eclipse.statet.jcommons.status.Statuses; |
| |
| import org.eclipse.statet.internal.r.rdata.REnvironmentVar; |
| import org.eclipse.statet.internal.r.rdata.RReferenceVar; |
| import org.eclipse.statet.internal.r.rdata.VirtualMissingVar; |
| import org.eclipse.statet.r.console.core.AbstractRController; |
| import org.eclipse.statet.r.console.core.RProcessREnvironment; |
| import org.eclipse.statet.r.console.core.RWorkspace; |
| import org.eclipse.statet.r.core.data.CombinedRElement; |
| import org.eclipse.statet.r.core.data.CombinedRList; |
| import org.eclipse.statet.r.core.model.RElementName; |
| import org.eclipse.statet.r.nico.ICombinedRDataAdapter; |
| import org.eclipse.statet.rj.data.RCharacterStore; |
| import org.eclipse.statet.rj.data.RDataUtils; |
| import org.eclipse.statet.rj.data.REnvironment; |
| import org.eclipse.statet.rj.data.RObject; |
| import org.eclipse.statet.rj.data.RReference; |
| import org.eclipse.statet.rj.data.RVector; |
| import org.eclipse.statet.rj.data.UnexpectedRDataException; |
| import org.eclipse.statet.rj.services.RService; |
| |
| |
| public class RObjectDB { |
| |
| |
| private static final Set<Long> NO_ENVS_SET= Collections.emptySet(); |
| |
| |
| private static class NamespaceEntry { |
| |
| private volatile VirtualMissingVar na; |
| |
| private REnvironmentVar namespaceEnv; |
| |
| private REnvironmentVar namespaceExports; |
| |
| private REnvironmentVar packageEnv; |
| |
| } |
| |
| private static class EnvironmentEntry { |
| |
| private final REnvironmentVar env; |
| |
| private byte checking; |
| private byte checked; |
| |
| public EnvironmentEntry(final REnvironmentVar env) { |
| this.env= env; |
| } |
| |
| } |
| |
| |
| private static boolean isNamespaceEnv(final RElementName elementName) { |
| return (elementName != null && elementName.getType() == RElementName.SCOPE_NS_INT |
| && elementName.getNextSegment() == null ); |
| } |
| |
| private static CombinedRElement first(final CombinedRElement first, final CombinedRElement second) { |
| return (first != null) ? first : second; |
| } |
| |
| private static final byte UPTODATE= RWorkspace.RESOLVE_UPTODATE; |
| private static final byte RECURSIVE= RWorkspace.RESOLVE_RECURSIVE; |
| private static final byte RECURSIVE_UPTODATE= RECURSIVE << 1; |
| |
| /** workspace flags -> this mode */ |
| public static byte toResolveMode(int resolve) { |
| resolve&= (UPTODATE | RECURSIVE); |
| if (resolve == (UPTODATE | RECURSIVE)) { |
| resolve|= RECURSIVE_UPTODATE; |
| } |
| return (byte) resolve; |
| } |
| |
| |
| private final RWorkspace workspace; |
| |
| private final ConcurrentHashMap<Long, EnvironmentEntry> envsMap= new ConcurrentHashMap<>(); |
| |
| private int searchEnvsStamp; |
| private List<REnvironmentVar> searchEnvs; |
| private List<? extends RProcessREnvironment> searchEnvsPublic; |
| |
| private int lazyEnvsStamp; |
| private Set<Long> lazyEnvs; |
| |
| private final ConcurrentHashMap<String, RObjectDB.NamespaceEntry> namespaceMap= new ConcurrentHashMap<>(); |
| private List<String> forceUpdatePkgNames; |
| |
| private RObjectDB previousDB; |
| private byte resolveMode; |
| |
| private ICombinedRDataAdapter r; |
| |
| |
| public RObjectDB(final RWorkspace workspace, final int stamp, |
| final AbstractRController r, final ProgressMonitor m) { |
| this.workspace= r.getWorkspaceData(); |
| |
| this.searchEnvsStamp= stamp; |
| this.searchEnvsPublic= Collections.emptyList(); |
| this.lazyEnvs= NO_ENVS_SET; |
| |
| updateLazyEnvs(r, m); |
| } |
| |
| |
| public List<? extends RProcessREnvironment> getSearchEnvs() { |
| return this.searchEnvsPublic; |
| } |
| |
| public int getSearchEnvsStamp() { |
| return this.searchEnvsStamp; |
| } |
| |
| public int getSearchEnvsElementCount() { |
| int count= 0; |
| for (final REnvironmentVar env : this.searchEnvs) { |
| if (env != null) { |
| final long l= env.getLength(); |
| if (l > 0) { |
| count+= l; |
| } |
| } |
| } |
| return count; |
| } |
| |
| public REnvironmentVar getEnv(final Long handle) { |
| final EnvironmentEntry entry= this.envsMap.get(handle); |
| return (entry != null) ? entry.env : null; |
| } |
| |
| public CombinedRElement getNamespaceEnv(final String name) { |
| if (name != null) { |
| final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name); |
| if (entry != null) { |
| return first(entry.na, entry.namespaceEnv); |
| } |
| } |
| return null; |
| } |
| |
| public CombinedRElement getNamespacePub(final String name) { |
| if (name != null) { |
| final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name); |
| if (entry != null) { |
| return first(entry.na, entry.namespaceExports); |
| } |
| } |
| return null; |
| } |
| |
| public boolean isNamespaceLoaded(final String name) { |
| if (name != null) { |
| final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name); |
| return (entry != null && entry.na == null); |
| } |
| return false; |
| } |
| |
| public CombinedRElement getPackageEnv(final String name) { |
| if (name != null) { |
| final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name); |
| if (entry != null) { |
| return first(entry.na, entry.packageEnv); |
| } |
| } |
| return null; |
| } |
| |
| public REnvironmentVar getSearchEnv(final String name) { |
| if (name != null) { |
| for (final REnvironmentVar env : this.searchEnvs) { |
| final RElementName elementName= env.getElementName(); |
| if (elementName != null && elementName.getType() == RElementName.SCOPE_SEARCH_ENV |
| && name.equals(elementName.getSegmentName())) { |
| return env; |
| } |
| } |
| } |
| return null; |
| } |
| |
| public CombinedRElement getByName(final RElementName name) { |
| switch (name.getType()) { |
| case RElementName.SCOPE_NS: |
| return getNamespacePub(name.getSegmentName()); |
| case RElementName.SCOPE_NS_INT: |
| return getNamespaceEnv(name.getSegmentName()); |
| case RElementName.SCOPE_SEARCH_ENV: |
| return getSearchEnv(name.getSegmentName()); |
| case RElementName.SCOPE_PACKAGE: |
| return getPackageEnv(name.getSegmentName()); |
| default: |
| return null; |
| } |
| } |
| |
| |
| public int getLazyEnvsStamp() { |
| return this.lazyEnvsStamp; |
| } |
| |
| public void updateLazyEnvs(final AbstractRController r, final ProgressMonitor m) { |
| if (this.envsMap != null && !this.envsMap.isEmpty() && !this.lazyEnvs.isEmpty()) { |
| this.envsMap.keySet().removeAll(this.lazyEnvs); |
| } |
| this.lazyEnvsStamp= r.getChangeStamp(); |
| final Set<Long> list= r.getLazyEnvironments(m); |
| this.lazyEnvs= (list != null && !list.isEmpty()) ? list : NO_ENVS_SET; |
| } |
| |
| public List<REnvironmentVar> update( |
| final Set<RElementName> envs, RObjectDB previous, final boolean force, |
| final ICombinedRDataAdapter r, final ProgressMonitor m) throws StatusException { |
| this.r= r; |
| try { |
| updateSearchList(m); |
| updateNamespaceList(m); |
| |
| if (m.isCanceled()) { |
| return null; |
| } |
| |
| List<String> forcePkgNames= null; |
| if (previous != null) { |
| if (force) { |
| previous= null; |
| } |
| else { |
| forcePkgNames= previous.forceUpdatePkgNames; |
| } |
| } |
| |
| final IntList updateList= createUpdateIdxs(envs, previous, forcePkgNames); |
| final List<REnvironmentVar> updateEnvs= createUpdateEnvs(updateList, m); |
| |
| updateEnvMap(updateEnvs, previous, forcePkgNames, m); |
| |
| if (previous != null) { |
| for (final Map.Entry<String, RObjectDB.NamespaceEntry> entry : previous.namespaceMap.entrySet()) { |
| final String name= entry.getKey(); |
| if (forcePkgNames != null && forcePkgNames.contains(name)) { |
| continue; |
| } |
| |
| final RObjectDB.NamespaceEntry oldEntry= entry.getValue(); |
| final RObjectDB.NamespaceEntry newEntry= this.namespaceMap.get(name); |
| if (oldEntry == null || oldEntry.na != null || newEntry == null) { |
| continue; |
| } |
| |
| if (newEntry.namespaceEnv == null) { |
| newEntry.namespaceEnv= oldEntry.namespaceEnv; |
| } |
| if (newEntry.namespaceExports == null) { |
| newEntry.namespaceExports= oldEntry.namespaceExports; |
| } |
| } |
| } |
| |
| return updateEnvs; |
| } |
| catch (final UnexpectedRDataException e) { |
| throw new StatusException(new ErrorStatus(RConsoleCorePlugin.BUNDLE_ID, |
| "Unexpected return value from R.", |
| e )); |
| } |
| finally { |
| this.r= null; |
| } |
| } |
| |
| private void updateSearchList(final ProgressMonitor m) throws StatusException, |
| UnexpectedRDataException { |
| this.searchEnvsStamp= this.r.getChangeStamp(); |
| this.searchEnvs= new ArrayList<>(); |
| this.searchEnvsPublic= Collections.unmodifiableList(this.searchEnvs); |
| final RVector<RCharacterStore> searchObj= RDataUtils.checkRCharVector( |
| this.r.evalData("base::search()", m)); //$NON-NLS-1$ |
| |
| final RCharacterStore namesData= searchObj.getData(); |
| for (int i= 0; i < namesData.getLength(); i++) { |
| if (namesData.isNA(i)) { |
| continue; |
| } |
| final String name= namesData.getChar(i); |
| this.searchEnvs.add(new REnvironmentVar(name, true, null, null)); |
| } |
| } |
| |
| private void updateNamespaceList(final ProgressMonitor m) |
| throws StatusException, UnexpectedRDataException { |
| final RVector<RCharacterStore> searchObj= RDataUtils.checkRCharVector( |
| this.r.evalData("base::loadedNamespaces()", m )); //$NON-NLS-1$ |
| |
| final RCharacterStore namesData= searchObj.getData(); |
| for (int i= 0; i < namesData.getLength(); i++) { |
| if (namesData.isNA(i)) { |
| continue; |
| } |
| final String name= namesData.getChar(i); |
| getNamespaceEntry(name); |
| } |
| } |
| |
| public IntList createUpdateIdxs(final Set<RElementName> envs, |
| final RObjectDB previous, final List<String> forcePkgNames) { |
| final IntList updateIdxs= new IntArrayList(this.searchEnvs.size()); |
| if (previous == null) { |
| for (int newIdx= 0; newIdx < this.searchEnvs.size(); newIdx++) { |
| updateIdxs.add(newIdx); |
| } |
| } |
| else { |
| // reuse environments until we found a new or any none-package item |
| int newIdx= this.searchEnvs.size() - 1; |
| for (int oldIdx= previous.searchEnvs.size(); newIdx >= 0; newIdx--) { |
| final REnvironmentVar current= this.searchEnvs.get(newIdx); |
| final String pkgName; |
| if (current.getSpecialType() > 0 && current.getSpecialType() <= REnvironment.ENVTYPE_PACKAGE |
| && (forcePkgNames == null || (pkgName= getPkgName(current)) == null |
| || !forcePkgNames.contains(pkgName) )) { |
| final int j= previous.searchEnvs.indexOf(current); |
| if (j >= 0 && j < oldIdx) { |
| oldIdx= j; |
| if (envs != null && envs.contains(current.getElementName())) { |
| updateIdxs.add(newIdx); |
| } |
| else { |
| this.searchEnvs.set(newIdx, previous.searchEnvs.get(oldIdx)); |
| } |
| continue; |
| } |
| } |
| break; |
| } |
| |
| for (; newIdx >= 0; newIdx--) { |
| updateIdxs.add(newIdx); |
| } |
| } |
| return updateIdxs; |
| } |
| |
| private List<REnvironmentVar> createUpdateEnvs(final IntList updateIdxs, |
| final ProgressMonitor m) throws StatusException { |
| final ArrayList<REnvironmentVar> updateEnvs= new ArrayList<>(updateIdxs.size()); |
| for (int idx= 0; idx < updateIdxs.size(); idx++) { |
| if (m.isCanceled()) { |
| throw new StatusException(Statuses.CANCEL_STATUS); |
| } |
| // Debug code |
| // if (item.getName().equals("methods")) { |
| { final REnvironmentVar env= this.searchEnvs.get(idx); |
| // final RVector<RCharacterStore> ls= (RVector<RCharacterStore>) tools.evalData("ls(name=\""+item.getId()+"\", all.names=TRUE)", monitor); |
| // final RCharacterStore lsData= ls.getData(); |
| // for (int i= 0; i < lsData.getLength(); i++) { |
| // final String elementName= lsData.getChar(i); |
| //// final String elementName= lsData.getChar(133); |
| // System.out.println(item.getId() + " " + elementName); |
| // final RObject element= tools.evalStruct("as.environment(\""+item.getId()+"\")$\""+elementName+"\"", monitor); |
| // System.out.println(element); |
| // } |
| |
| // Regular code |
| final RElementName elementName= env.getElementName(); |
| try { |
| // long start= System.currentTimeMillis(); |
| final int loadOptions= RService.LOAD_PROMISE; |
| final RObject robject= this.r.evalCombinedStruct(elementName, |
| loadOptions, RService.DEPTH_INFINITE, |
| m ); |
| // long end= System.currentTimeMillis(); |
| // System.out.println("update " + elementName.getDisplayName() + ": " + (end-start)); |
| // System.out.println(robject); |
| if (robject != null && robject.getRObjectType() == RObject.TYPE_ENVIRONMENT) { |
| final REnvironmentVar newEnv= (REnvironmentVar) robject; |
| this.searchEnvs.set(idx, newEnv); |
| updateEnvs.add(newEnv); |
| continue; |
| } |
| } |
| catch (final StatusException e) { |
| RConsoleCorePlugin.logError("Error update environment "+ elementName, e); |
| if (this.r.getTool().isTerminated() || m.isCanceled()) { |
| throw e; |
| } |
| } |
| env.setError("update error"); |
| updateEnvs.add(env); |
| |
| // final RObject test= tools.evalStruct("yy", monitor); |
| // System.out.println(test); |
| } |
| } |
| return updateEnvs; |
| } |
| |
| private RObjectDB.NamespaceEntry getNamespaceEntry(final String name) { |
| RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name); |
| if (entry == null) { |
| entry= new NamespaceEntry(); |
| this.namespaceMap.put(name, entry); |
| } |
| return entry; |
| } |
| |
| private String getPkgName(final REnvironmentVar env) { |
| switch (env.getSpecialType()) { |
| case REnvironment.ENVTYPE_BASE: |
| return REnvironment.ENVNAME_BASE; |
| case REnvironment.ENVTYPE_PACKAGE: |
| return env.getEnvironmentName().substring(8); |
| case REnvironment.ENVTYPE_NAMESPACE: |
| return env.getEnvironmentName(); |
| case REnvironment.ENVTYPE_NAMESPACE_EXPORTS: |
| return env.getEnvironmentName(); |
| default: |
| return null; |
| } |
| } |
| |
| private EnvironmentEntry registerEnv(final Long handle, final REnvironmentVar env, |
| final boolean isUptodate) { |
| final EnvironmentEntry environmentEntry; |
| if (handle != null) { |
| environmentEntry= new EnvironmentEntry(env); |
| this.envsMap.put(handle, environmentEntry); |
| } |
| else { |
| environmentEntry= null; |
| } |
| |
| final String name= getPkgName(env); |
| if (name != null) { |
| final RObjectDB.NamespaceEntry entry= getNamespaceEntry(name); |
| switch (env.getSpecialType()) { |
| case REnvironment.ENVTYPE_BASE: |
| case REnvironment.ENVTYPE_PACKAGE: |
| if (isUptodate || (entry.na == null && entry.packageEnv == null)) { |
| entry.packageEnv= env; |
| } |
| break; |
| case REnvironment.ENVTYPE_NAMESPACE: |
| if (isUptodate || (entry.na == null && entry.namespaceEnv == null)) { |
| entry.namespaceEnv= env; |
| } |
| break; |
| case REnvironment.ENVTYPE_NAMESPACE_EXPORTS: |
| if (isUptodate || (entry.na == null && entry.namespaceExports == null)) { |
| entry.namespaceExports= env; |
| } |
| break; |
| default: |
| return environmentEntry; |
| } |
| |
| if (isUptodate) { |
| entry.na= null; |
| } |
| } |
| return environmentEntry; |
| } |
| |
| private void registerNA(final VirtualMissingVar na) { |
| final RObjectDB.NamespaceEntry entry= getNamespaceEntry(na.getElementName().getSegmentName()); |
| entry.na= na; |
| entry.namespaceEnv= null; |
| entry.namespaceExports= null; |
| } |
| |
| private void updateEnvMap(final List<REnvironmentVar> updateEnvs, final RObjectDB previous, |
| final List<String> forcePkgNames, |
| final ProgressMonitor m) throws StatusException { |
| if (m.isCanceled()) { |
| return; |
| } |
| this.previousDB= null; |
| this.resolveMode= RECURSIVE; |
| |
| for (final REnvironmentVar env : this.searchEnvs) { |
| registerEnv(Long.valueOf(env.getHandle()), env, true); |
| } |
| |
| for (final REnvironmentVar env : updateEnvs) { |
| final Long handle= Long.valueOf(env.getHandle()); |
| EnvironmentEntry entry= this.envsMap.get(handle); |
| if (entry == null) { |
| entry= registerEnv(handle, env, true); |
| } |
| check(entry, m); |
| } |
| this.previousDB= previous; |
| this.forceUpdatePkgNames= forcePkgNames; |
| for (final REnvironmentVar env : this.searchEnvs) { |
| if (!updateEnvs.contains(env)) { |
| check(env, m); |
| } |
| } |
| this.previousDB= null; |
| this.forceUpdatePkgNames= null; |
| return; |
| } |
| |
| public CombinedRElement resolve(final RReferenceVar ref, final int resolve, |
| final int loadOptions, |
| final ICombinedRDataAdapter r, final ProgressMonitor m) throws StatusException { |
| this.r= r; |
| this.resolveMode= toResolveMode(resolve); |
| try { |
| final CombinedRElement resolved= evalResolve(ref, ref.getElementName(), |
| loadOptions, m ); |
| |
| if (resolved != null) { |
| checkDirectAccessName(resolved, ref.getElementName()); |
| } |
| |
| return resolved; |
| } |
| finally { |
| this.r= null; |
| } |
| } |
| |
| private CombinedRElement evalResolve(final RReferenceVar ref, final RElementName fullName, |
| int loadOptions, |
| final ProgressMonitor m) throws StatusException { |
| Long handle= (ref.getHandle() != 0) ? Long.valueOf(ref.getHandle()) : null; |
| final byte mode= this.resolveMode; |
| |
| try { |
| this.resolveMode= ((mode & RECURSIVE_UPTODATE) != 0) ? mode : (byte) (mode & ~UPTODATE); |
| boolean lazy= false; |
| if (ref.getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT && handle != null) { |
| ref.setResolver(this.workspace); |
| |
| { final EnvironmentEntry entry= this.envsMap.get(handle); |
| if (entry != null) { |
| if ((mode & UPTODATE) == 0 |
| || entry.env.getStamp() == this.r.getChangeStamp() ) { |
| check(entry, m); |
| return entry.env; |
| } |
| // we are about to replace an environment because of wrong stamp |
| // to be save, resolve all (for object browser), but correct stamp |
| // can be loaded later (like this request) |
| this.resolveMode|= RECURSIVE; |
| } |
| } |
| |
| lazy= this.lazyEnvs.contains(handle); |
| if (!lazy && this.previousDB != null) { |
| final EnvironmentEntry prevEntry= this.previousDB.envsMap.get(handle); |
| final List<String> forcePkgNames= this.forceUpdatePkgNames; |
| final String pkgName; |
| if (prevEntry != null |
| && ((mode & UPTODATE) == 0 |
| || (prevEntry.env.getStamp() == this.r.getChangeStamp())) |
| && (forcePkgNames == null || (pkgName= getPkgName(prevEntry.env)) == null |
| || !forcePkgNames.contains(pkgName) )) { |
| final EnvironmentEntry entry= registerEnv(handle, prevEntry.env, false); |
| if (entry != null) { |
| check(entry, m); |
| return entry.env; |
| } |
| } |
| } |
| } |
| |
| CombinedRElement element= null; |
| if (ref.getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT && handle != null) { |
| if (!(lazy || isNamespaceEnv(ref.getElementName()) )) { |
| loadOptions|= RService.LOAD_PROMISE; |
| } |
| element= this.r.evalCombinedStruct(ref, |
| loadOptions, RService.DEPTH_INFINITE, null, m ); |
| } |
| else if (fullName != null) { |
| if (!(lazy || isNamespaceEnv(fullName) )) { |
| loadOptions|= RService.LOAD_PROMISE; |
| } |
| final RElementName symbolName= fullName.getLastSegment(); |
| if (symbolName.getType() == RElementName.MAIN_DEFAULT) { |
| final RElementName envName= RElementName.create(fullName, symbolName, true); |
| try { |
| element= this.r.findCombinedStruct(symbolName, envName, false, |
| loadOptions, RService.DEPTH_INFINITE, m ); |
| } |
| catch (final StatusException e) { |
| } |
| } |
| if (element == null) { |
| element= this.r.evalCombinedStruct(fullName, |
| loadOptions, RService.DEPTH_INFINITE, m ); |
| } |
| } |
| else { |
| throw new StatusException(new ErrorStatus(RConsoleCorePlugin.BUNDLE_ID, |
| "Unsupported ref: " + ref )); |
| } |
| if (element != null && element.getRObjectType() == RObject.TYPE_ENVIRONMENT) { |
| final REnvironmentVar env= (REnvironmentVar) element; |
| if (handle == null && env.getHandle() != 0) { |
| handle= Long.valueOf(env.getHandle()); |
| } |
| final EnvironmentEntry entry= registerEnv(handle, env, true); |
| if (entry != null) { |
| check(entry, m); |
| return env; |
| } |
| } |
| if (element instanceof CombinedRList) { |
| check((CombinedRList) element, m); |
| } |
| return element; |
| } |
| catch (final StatusException e) { |
| if (fullName != null |
| &&fullName.getNextSegment() == null |
| && RElementName.isPackageFacetScopeType(fullName.getType()) ) { |
| final VirtualMissingVar na= new VirtualMissingVar(fullName, |
| this.r.getTool(), this.r.getChangeStamp()); |
| registerNA(na); |
| } |
| |
| RConsoleCorePlugin.logError("Error update ref: " + ref.getElementName(), e); |
| if (this.r.getTool().isTerminated() || m.isCanceled()) { |
| throw e; |
| } |
| return null; |
| } |
| finally { |
| this.resolveMode= mode; |
| } |
| } |
| |
| private void checkDirectAccessName(final CombinedRElement var, final RElementName name) { |
| if (name == null || name.getNextSegment() != null) { |
| return; |
| } |
| |
| if (var instanceof REnvironmentVar && RElementName.isScopeType(name.getType())) { |
| ((REnvironmentVar) var).setElementName(name); |
| } |
| } |
| |
| private void check(final EnvironmentEntry entry, |
| final ProgressMonitor m) throws StatusException { |
| final byte mode= (byte) (UPTODATE | this.resolveMode); // UPTODATE -> check to setResolver |
| if ((mode & ~(entry.checked | entry.checking)) != 0) { |
| final byte was= entry.checking; |
| entry.checking|= mode; |
| try { |
| check(entry.env, m); |
| entry.checked|= mode; |
| } |
| finally { |
| entry.checking= was; |
| } |
| } |
| } |
| |
| private void check(final CombinedRList list, |
| final ProgressMonitor m) throws StatusException { |
| if (list.hasModelChildren(null)) { |
| final long length= list.getLength(); |
| if (length <= Integer.MAX_VALUE) { |
| final int l= (int) length; |
| ITER_CHILDREN : for (int i= 0; i < l; i++) { |
| final RObject object= list.get(i); |
| if (object != null) { |
| switch (object.getRObjectType()) { |
| case RObject.TYPE_REFERENCE: |
| if ((this.resolveMode & RECURSIVE) != 0 |
| && ((RReference) object).getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT) { |
| evalResolve((RReferenceVar) object, null, 0, m); |
| } |
| else { |
| ((RReferenceVar) object).setResolver(this.workspace); |
| } |
| continue ITER_CHILDREN; |
| case RObject.TYPE_LIST: |
| case RObject.TYPE_S4OBJECT: |
| check((CombinedRList) object, m); |
| continue ITER_CHILDREN; |
| default: |
| continue ITER_CHILDREN; |
| } |
| } |
| } |
| } |
| else { |
| ITER_CHILDREN : for (long i= 0; i < length; i++) { |
| final RObject object= list.get(i); |
| if (object != null) { |
| switch (object.getRObjectType()) { |
| case RObject.TYPE_REFERENCE: |
| if ((this.resolveMode & RECURSIVE) != 0 |
| && ((RReference) object).getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT) { |
| evalResolve((RReferenceVar) object, null, 0, m); |
| } |
| else { |
| ((RReferenceVar) object).setResolver(this.workspace); |
| } |
| continue ITER_CHILDREN; |
| case RObject.TYPE_LIST: |
| case RObject.TYPE_S4OBJECT: |
| check((CombinedRList) object, m); |
| continue ITER_CHILDREN; |
| default: |
| continue ITER_CHILDREN; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| public void handleRPkgChange(final List<String> names) { |
| this.forceUpdatePkgNames= (this.forceUpdatePkgNames != null) ? |
| ImCollections.concatList(this.forceUpdatePkgNames, names) : |
| names; |
| } |
| |
| } |