/******************************************************************************* * Copyright (c) 2004, 2011 IBM Corporation 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation * Markus Schorn (Wind River Systems) * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig2; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.Map.Entry; import org.eclipse.cdt.internal.core.SafeStringInterner; import org.eclipse.cdt.make.core.MakeCorePlugin; import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector3; import org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorCleaner; import org.eclipse.cdt.make.core.scannerconfig.InfoContext; import org.eclipse.cdt.make.core.scannerconfig.PathInfo; import org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes; import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo; import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredScannerInfoSerializable; import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo; import org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo2; import org.eclipse.cdt.make.internal.core.MakeMessages; import org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore; import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerConfigUtil; import org.eclipse.cdt.make.internal.core.scannerconfig.util.CCommandDSC; import org.eclipse.cdt.make.internal.core.scannerconfig.util.CygpathTranslator; import org.eclipse.cdt.make.internal.core.scannerconfig.util.TraceUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Per file scanner info collector * * @author vhirsl */ public class PerFileSICollector implements IScannerInfoCollector3, IScannerInfoCollectorCleaner { protected static final int INCLUDE_PATH = 1; protected static final int QUOTE_INCLUDE_PATH = 2; protected static final int INCLUDE_FILE = 3; protected static final int MACROS_FILE = 4; protected class ScannerInfoData implements IDiscoveredScannerInfoSerializable { protected final Map<Integer, Set<IFile>> commandIdToFilesMap; // command id and set of files it applies to protected final Map<IFile, Integer> fileToCommandIdMap; // maps each file to the corresponding command id protected final Map<Integer, CCommandDSC> commandIdCommandMap; // map of all commands public ScannerInfoData() { commandIdCommandMap = new LinkedHashMap<Integer, CCommandDSC>(); // [commandId, command] fileToCommandIdMap = new HashMap<IFile, Integer>(); // [file, commandId] commandIdToFilesMap = new HashMap<Integer, Set<IFile>>(); // [commandId, set of files] } /* (non-Javadoc) * @see org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore.IDiscoveredScannerInfoSerializable#serialize(org.w3c.dom.Element) */ public void serialize(Element collectorElem) { synchronized (PerFileSICollector.this.fLock) { Document doc = collectorElem.getOwnerDocument(); List<Integer> commandIds = new ArrayList<Integer>(commandIdCommandMap.keySet()); Collections.sort(commandIds); for (Integer commandId : commandIds) { CCommandDSC command = commandIdCommandMap.get(commandId); Element cmdElem = doc.createElement(CC_ELEM); collectorElem.appendChild(cmdElem); cmdElem.setAttribute(ID_ATTR, commandId.toString()); cmdElem.setAttribute(FILE_TYPE_ATTR, command.appliesToCPPFileType() ? "c++" : "c"); //$NON-NLS-1$ //$NON-NLS-2$ // write command and scanner info command.serialize(cmdElem); // write files command applies to Element filesElem = doc.createElement(APPLIES_TO_ATTR); cmdElem.appendChild(filesElem); Set<IFile> files = commandIdToFilesMap.get(commandId); if (files != null) { for (IFile file : files) { Element fileElem = doc.createElement(FILE_ELEM); IPath path = file.getProjectRelativePath(); fileElem.setAttribute(PATH_ATTR, path.toString()); filesElem.appendChild(fileElem); } } } } } /* (non-Javadoc) * @see org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore.IDiscoveredScannerInfoSerializable#deserialize(org.w3c.dom.Element) */ public void deserialize(Element collectorElem) { synchronized (PerFileSICollector.this.fLock) { for (Node child = collectorElem.getFirstChild(); child != null; child = child.getNextSibling()) { if (child.getNodeName().equals(CC_ELEM)) { Element cmdElem = (Element) child; boolean cppFileType = cmdElem.getAttribute(FILE_TYPE_ATTR).equals("c++"); //$NON-NLS-1$ CCommandDSC command = new CCommandDSC(cppFileType, project); command.setCommandId(Integer.parseInt(cmdElem.getAttribute(ID_ATTR))); // deserialize command command.deserialize(cmdElem); // get set of files the command applies to NodeList appliesList = cmdElem.getElementsByTagName(APPLIES_TO_ATTR); if (appliesList.getLength() > 0) { Element appliesElem = (Element) appliesList.item(0); NodeList fileList = appliesElem.getElementsByTagName(FILE_ELEM); for (int i = 0; i < fileList.getLength(); ++i) { Element fileElem = (Element) fileList.item(i); String fileName = fileElem.getAttribute(PATH_ATTR); IFile file = project.getFile(fileName); addCompilerCommand(file, command); } applyFileDeltas(); } } } } } /* (non-Javadoc) * @see org.eclipse.cdt.make.internal.core.scannerconfig.DiscoveredScannerInfoStore.IDiscoveredScannerInfoSerializable#getCollectorId() */ public String getCollectorId() { return COLLECTOR_ID; } } protected static class ProjectScannerInfo { IPath[] includePaths; IPath[] quoteIncludePaths; IPath[] includeFiles; IPath[] macrosFiles; Map<String, String> definedSymbols; public boolean isEmpty() { return (includePaths.length == 0 && quoteIncludePaths.length == 0 && includeFiles.length == 0 && macrosFiles.length == 0 && definedSymbols.size() == 0); } } public static final String COLLECTOR_ID = MakeCorePlugin.getUniqueIdentifier() + ".PerFileSICollector"; //$NON-NLS-1$ protected static final String CC_ELEM = "compilerCommand"; //$NON-NLS-1$ protected static final String ID_ATTR = "id"; //$NON-NLS-1$ protected static final String FILE_TYPE_ATTR = "fileType"; //$NON-NLS-1$ protected static final String APPLIES_TO_ATTR = "appliesToFiles"; //$NON-NLS-1$ protected static final String FILE_ELEM = "file"; //$NON-NLS-1$ protected static final String PATH_ATTR = "path"; //$NON-NLS-1$ protected IProject project; protected InfoContext context; protected ScannerInfoData sid; // scanner info data protected ProjectScannerInfo psi = null; // sum of all scanner info // protected List siChangedForFileList; // list of files for which scanner info has changed protected final Map<IFile, Integer> siChangedForFileMap; // (file, comandId) map for deltas protected final List<Integer> siChangedForCommandIdList; // list of command ids for which scanner info has changed protected final SortedSet<Integer> freeCommandIdPool; // sorted set of free command ids protected int commandIdCounter = 0; /** monitor for data access */ protected final Object fLock = new Object(); /** * */ public PerFileSICollector() { sid = new ScannerInfoData(); // siChangedForFileList = new ArrayList(); siChangedForFileMap = new HashMap<IFile, Integer>(); siChangedForCommandIdList = new ArrayList<Integer>(); freeCommandIdPool = new TreeSet<Integer>(); } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2#setProject(org.eclipse.core.resources.IProject) */ public void setProject(IProject project) { setInfoContext(new InfoContext(project)); } public void setInfoContext(InfoContext context) { this.project = context.getProject(); this.context = context; try { // deserialize from SI store DiscoveredScannerInfoStore.getInstance().loadDiscoveredScannerInfoFromState(project, context, sid); } catch (CoreException e) { MakeCorePlugin.log(e); } } protected InfoContext getInfoContext() { return context; } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector#contributeToScannerConfig(java.lang.Object, java.util.Map) */ public void contributeToScannerConfig(Object resource, @SuppressWarnings("rawtypes") Map scannerInfo) { // check the resource String errorMessage = null; if (resource == null) { errorMessage = "resource is null";//$NON-NLS-1$ } else if (resource instanceof Integer) { synchronized (fLock) { @SuppressWarnings("unchecked") Map<ScannerInfoTypes, List<String>> scanInfo = scannerInfo; addScannerInfo(((Integer)resource), scanInfo); } return; } else if (!(resource instanceof IFile)) { errorMessage = "resource is not an IFile";//$NON-NLS-1$ } else if (((IFile) resource).getProject() == null) { errorMessage = "project is null";//$NON-NLS-1$ } else if (!((IFile) resource).getProject().equals(project)) { errorMessage = "wrong project";//$NON-NLS-1$ } if (errorMessage != null) { TraceUtil.outputError("PerFileSICollector.contributeToScannerConfig : ", errorMessage); //$NON-NLS-1$ return; } IFile file = (IFile) resource; synchronized (fLock) { @SuppressWarnings("unchecked") Map<ScannerInfoTypes, List<CCommandDSC>> scanInfo = scannerInfo; Set<ScannerInfoTypes> types = scanInfo.keySet(); for (ScannerInfoTypes type : types) { if (type.equals(ScannerInfoTypes.COMPILER_COMMAND)) { List<CCommandDSC> commands = scanInfo.get(type); for (CCommandDSC cmd : commands) { addCompilerCommand(file, cmd); } } else { addScannerInfo(type, scanInfo.get(type)); } } } } protected void addScannerInfo(Integer commandId, Map<ScannerInfoTypes, List<String>> scannerInfo) { assert Thread.holdsLock(fLock); CCommandDSC cmd = sid.commandIdCommandMap.get(commandId); if (cmd != null) { List<String> siItem = scannerInfo.get(ScannerInfoTypes.SYMBOL_DEFINITIONS); cmd.setSymbols(siItem); siItem = scannerInfo.get(ScannerInfoTypes.INCLUDE_PATHS); siItem = CygpathTranslator.translateIncludePaths(project, siItem); siItem = CCommandDSC.makeRelative(project, siItem); cmd.setIncludes(siItem); siItem = scannerInfo.get(ScannerInfoTypes.QUOTE_INCLUDE_PATHS); siItem = CygpathTranslator.translateIncludePaths(project, siItem); siItem = CCommandDSC.makeRelative(project, siItem); cmd.setQuoteIncludes(siItem); cmd.setDiscovered(true); } } protected void addCompilerCommand(IFile file, CCommandDSC cmd) { assert Thread.holdsLock(fLock); List<CCommandDSC> existingCommands = new ArrayList<CCommandDSC>(sid.commandIdCommandMap.values()); int index = existingCommands.indexOf(cmd); if (index != -1) { cmd = existingCommands.get(index); } else { int commandId = -1; if (!freeCommandIdPool.isEmpty()) { Integer freeCommandId = freeCommandIdPool.first(); freeCommandIdPool.remove(freeCommandId); commandId = freeCommandId.intValue(); } else { commandId = ++commandIdCounter; } cmd.setCommandId(commandId); sid.commandIdCommandMap.put(cmd.getCommandIdAsInteger(), cmd); } generateFileDelta(file, cmd); } protected void generateFileDelta(IFile file, CCommandDSC cmd) { assert Thread.holdsLock(fLock); Integer commandId = cmd.getCommandIdAsInteger(); Integer oldCommandId = sid.fileToCommandIdMap.get(file); if (oldCommandId != null && oldCommandId.equals(commandId)) { // already exists; remove form delta siChangedForFileMap.remove(file); } else { // new (file, commandId) pair siChangedForFileMap.put(file, commandId); } } protected void applyFileDeltas() { assert Thread.holdsLock(fLock); Set<IFile> resources = siChangedForFileMap.keySet(); for (IFile file : resources) { Integer commandId = siChangedForFileMap.get(file); if (commandId != null) { // update sid.commandIdToFilesMap Set<IFile> fileSet = sid.commandIdToFilesMap.get(commandId); if (fileSet == null) { fileSet = new HashSet<IFile>(); sid.commandIdToFilesMap.put(commandId, fileSet); CCommandDSC cmd = sid.commandIdCommandMap.get(commandId); if (cmd != null) { cmd.resolveOptions(project); } } if (fileSet.add(file)) { // update fileToCommandIdsMap boolean change = true; Integer oldCommandId = sid.fileToCommandIdMap.get(file); if (oldCommandId != null) { if (oldCommandId.equals(commandId)) { change = false; } else { Set<IFile> oldFileSet = sid.commandIdToFilesMap.get(oldCommandId); if (oldFileSet != null) { oldFileSet.remove(file); } } } if (change) { sid.fileToCommandIdMap.put(file, commandId); // TODO generate change event for this resource // IPath path = file.getFullPath(); // if (!siChangedForFileList.contains(path)) { // siChangedForFileList.add(path); // } } } } } generateProjectScannerInfo(); } protected void generateProjectScannerInfo() { assert Thread.holdsLock(fLock); psi = new ProjectScannerInfo(); psi.includePaths = getAllIncludePaths(INCLUDE_PATH); psi.quoteIncludePaths = getAllIncludePaths(QUOTE_INCLUDE_PATH); psi.includeFiles = getAllIncludePaths(INCLUDE_FILE); psi.macrosFiles = getAllIncludePaths(MACROS_FILE); psi.definedSymbols = getAllSymbols(); } protected void removeUnusedCommands() { assert Thread.holdsLock(fLock); Set<Entry<Integer, Set<IFile>>> entrySet = sid.commandIdToFilesMap.entrySet(); for (Entry<Integer, Set<IFile>> entry : entrySet) { Integer cmdId = entry.getKey(); Set<IFile> fileSet = entry.getValue(); if (fileSet.isEmpty()) { // return cmdId to the free command id pool freeCommandIdPool.add(cmdId); } } for (Integer cmdId : freeCommandIdPool) { // the command does not have any files associated; remove sid.commandIdCommandMap.remove(cmdId); sid.commandIdToFilesMap.remove(cmdId); } while (!freeCommandIdPool.isEmpty()) { Integer last = freeCommandIdPool.last(); if (last.intValue() == commandIdCounter) { freeCommandIdPool.remove(last); --commandIdCounter; } else break; } } protected void addScannerInfo(ScannerInfoTypes type, List<CCommandDSC> delta) { // TODO Auto-generated method stub } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2#updateScannerConfiguration(org.eclipse.core.runtime.IProgressMonitor) */ public void updateScannerConfiguration(IProgressMonitor monitor) throws CoreException { if (monitor == null) { monitor = new NullProgressMonitor(); } monitor.beginTask(MakeMessages.getString("ScannerInfoCollector.Processing"), 100); //$NON-NLS-1$ monitor.subTask(MakeMessages.getString("ScannerInfoCollector.Processing")); //$NON-NLS-1$ ArrayList<IResource> changedResources = null; synchronized (fLock) { if (scannerInfoChanged()) { applyFileDeltas(); removeUnusedCommands(); changedResources = new ArrayList<IResource>(siChangedForFileMap.keySet()); siChangedForFileMap.clear(); } siChangedForCommandIdList.clear(); } monitor.worked(50); if (changedResources != null) { // update outside monitor scope try { // update scanner configuration monitor.subTask(MakeMessages.getString("ScannerInfoCollector.Updating") + project.getName()); //$NON-NLS-1$ IDiscoveredPathInfo pathInfo = MakeCorePlugin.getDefault().getDiscoveryManager().getDiscoveredInfo(project, context); if (!(pathInfo instanceof IPerFileDiscoveredPathInfo)) { pathInfo = createPathInfoObject(); } MakeCorePlugin.getDefault().getDiscoveryManager().updateDiscoveredInfo(context, pathInfo, context.isDefaultContext(), changedResources); } catch (CoreException e) { MakeCorePlugin.log(e); } } monitor.worked(50); monitor.done(); } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector2#createPathInfoObject() */ public IDiscoveredPathInfo createPathInfoObject() { return new PerFileDiscoveredPathInfo(); } protected boolean scannerInfoChanged() { assert Thread.holdsLock(fLock); // return !siChangedForFileList.isEmpty(); return !siChangedForFileMap.isEmpty(); } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollector#getCollectedScannerInfo(java.lang.Object, org.eclipse.cdt.make.core.scannerconfig.ScannerInfoTypes) */ public List<CCommandDSC> getCollectedScannerInfo(Object resource, ScannerInfoTypes type) { List<CCommandDSC> rv = new ArrayList<CCommandDSC>(); // check the resource String errorMessage = null; if (resource == null) { errorMessage = "resource is null";//$NON-NLS-1$ } else if (!(resource instanceof IResource)) { errorMessage = "resource is not an IResource";//$NON-NLS-1$ } else if (((IResource) resource).getProject() == null) { errorMessage = "project is null";//$NON-NLS-1$ } else if (((IResource) resource).getProject() != project) { errorMessage = "wrong project";//$NON-NLS-1$ } if (errorMessage != null) { TraceUtil.outputError("PerProjectSICollector.getCollectedScannerInfo : ", errorMessage); //$NON-NLS-1$ return rv; } if (resource!=null && project.equals(((IResource)resource).getProject())) { if (type.equals(ScannerInfoTypes.COMPILER_COMMAND)) { synchronized (fLock) { Set<Integer> cmdIds = sid.commandIdCommandMap.keySet(); for (Integer cmdId : cmdIds) { Set<IFile> fileSet = sid.commandIdToFilesMap.get(cmdId); if (fileSet != null && !fileSet.isEmpty()) { rv.add(sid.commandIdCommandMap.get(cmdId)); } } } } else if (type.equals(ScannerInfoTypes.UNDISCOVERED_COMPILER_COMMAND)) { // if (!siChangedForFileList.isEmpty()) { synchronized (fLock) { if (scannerInfoChanged()) { if (siChangedForCommandIdList.isEmpty()) { Set<IFile> files = siChangedForFileMap.keySet(); for (IFile file : files) { Integer cmdId = siChangedForFileMap.get(file); if (cmdId != null) { if (!siChangedForCommandIdList.contains(cmdId)) { siChangedForCommandIdList.add(cmdId); } } } } Collections.sort(siChangedForCommandIdList); for (Integer cmdId : siChangedForCommandIdList) { CCommandDSC command = sid.commandIdCommandMap.get(cmdId); rv.add(command); } } } } } return rv; } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorUtil#deleteAllPaths(org.eclipse.core.resources.IResource) */ public void deleteAllPaths(IResource resource) { // TODO Auto-generated method stub } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorUtil#deleteAllSymbols(org.eclipse.core.resources.IResource) */ public void deleteAllSymbols(IResource resource) { // TODO Auto-generated method stub } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorUtil#deletePath(org.eclipse.core.resources.IResource, java.lang.String) */ public void deletePath(IResource resource, String path) { // TODO Auto-generated method stub } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorUtil#deleteSymbol(org.eclipse.core.resources.IResource, java.lang.String) */ public void deleteSymbol(IResource resource, String symbol) { // TODO Auto-generated method stub } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IScannerInfoCollectorCleaner#deleteAll(org.eclipse.core.resources.IResource) */ public void deleteAll(IResource resource) { if (resource.equals(project)) { synchronized (fLock) { // siChangedForFileList = new ArrayList(); siChangedForFileMap.clear(); Set<IFile> changedFiles = sid.fileToCommandIdMap.keySet(); for (IFile file : changedFiles) { // IPath path = file.getFullPath(); // siChangedForFileList.add(path); siChangedForFileMap.put(file, null); } sid = new ScannerInfoData(); psi = null; commandIdCounter = 0; freeCommandIdPool.clear(); } } } /** * Per file DPI object * * @author vhirsl */ protected class PerFileDiscoveredPathInfo implements IPerFileDiscoveredPathInfo2 { /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getProject() */ public IProject getProject() { return project; } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getIncludePaths() */ public IPath[] getIncludePaths() { final IPath[] includepaths; final IPath[] quotepaths; synchronized (PerFileSICollector.this.fLock) { // return new IPath[0]; includepaths = getAllIncludePaths(INCLUDE_PATH); quotepaths = getAllIncludePaths(QUOTE_INCLUDE_PATH); } if (quotepaths == null || quotepaths.length == 0) { return includepaths; } if (includepaths == null || includepaths.length == 0) { return quotepaths; } ArrayList<IPath> result = new ArrayList<IPath>(includepaths.length + quotepaths.length); result.addAll(Arrays.asList(includepaths)); result.addAll(Arrays.asList(quotepaths)); return result.toArray(new IPath[result.size()]); } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getSymbols() */ public Map<String, String> getSymbols() { // return new HashMap(); synchronized (PerFileSICollector.this.fLock) { return getAllSymbols(); } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getIncludePaths(org.eclipse.core.runtime.IPath) */ public IPath[] getIncludePaths(IPath path) { synchronized (PerFileSICollector.this.fLock) { // get the command CCommandDSC cmd = getCommand(path); if (cmd != null && cmd.isDiscovered()) { return stringListToPathArray(cmd.getIncludes()); } // use project scope scanner info if (psi == null) { generateProjectScannerInfo(); } return psi.includePaths; } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo#getQuoteIncludePaths(org.eclipse.core.runtime.IPath) */ public IPath[] getQuoteIncludePaths(IPath path) { synchronized (PerFileSICollector.this.fLock) { // get the command CCommandDSC cmd = getCommand(path); if (cmd != null && cmd.isDiscovered()) { return stringListToPathArray(cmd.getQuoteIncludes()); } // use project scope scanner info if (psi == null) { generateProjectScannerInfo(); } return psi.quoteIncludePaths; } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getSymbols(org.eclipse.core.runtime.IPath) */ public Map<String, String> getSymbols(IPath path) { synchronized (PerFileSICollector.this.fLock) { // get the command CCommandDSC cmd = getCommand(path); if (cmd != null && cmd.isDiscovered()) { List<String> symbols = cmd.getSymbols(); Map<String, String> definedSymbols = new HashMap<String, String>(symbols.size()); for (String symbol : symbols) { String key = SafeStringInterner.safeIntern(ScannerConfigUtil.getSymbolKey(symbol)); String value = SafeStringInterner.safeIntern(ScannerConfigUtil.getSymbolValue(symbol)); definedSymbols.put(key, value); } return definedSymbols; } // use project scope scanner info if (psi == null) { generateProjectScannerInfo(); } return psi.definedSymbols; } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IDiscoveredPathInfo#getIncludeFiles(org.eclipse.core.runtime.IPath) */ public IPath[] getIncludeFiles(IPath path) { synchronized (PerFileSICollector.this.fLock) { // get the command CCommandDSC cmd = getCommand(path); if (cmd != null) { return stringListToPathArray(cmd.getIncludeFile()); } // use project scope scanner info if (psi == null) { generateProjectScannerInfo(); } return psi.includeFiles; } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo#getMacroFiles(org.eclipse.core.runtime.IPath) */ public IPath[] getMacroFiles(IPath path) { synchronized (PerFileSICollector.this.fLock) { // get the command CCommandDSC cmd = getCommand(path); if (cmd != null) { return stringListToPathArray(cmd.getImacrosFile()); } // use project scope scanner info if (psi == null) { generateProjectScannerInfo(); } return psi.macrosFiles; } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo#getSerializable() */ public IDiscoveredScannerInfoSerializable getSerializable() { synchronized (PerFileSICollector.this.fLock) { return sid; } } /* (non-Javadoc) * @see org.eclipse.cdt.make.core.scannerconfig.IDiscoveredPathManager.IPerFileDiscoveredPathInfo#isEmpty(org.eclipse.core.runtime.IPath) */ public boolean isEmpty(IPath path) { boolean rc = true; IResource resource = project.getWorkspace().getRoot().findMember(path); if (resource != null) { if (resource instanceof IFile) { rc = (getCommand((IFile)resource) == null); } else if (resource instanceof IProject) { synchronized (PerFileSICollector.this.fLock) { rc = (psi == null || psi.isEmpty()); } } } return rc; } public Map<IResource, PathInfo> getPathInfoMap() { synchronized (PerFileSICollector.this.fLock) { //TODO: do we need to cache this? return calculatePathInfoMap(); } } } protected Map<IResource, PathInfo> calculatePathInfoMap(){ assert Thread.holdsLock(fLock); Map<IResource, PathInfo> map = new HashMap<IResource, PathInfo>(sid.fileToCommandIdMap.size() + 1); Set<Entry<IFile, Integer>> entrySet = sid.fileToCommandIdMap.entrySet(); for (Entry<IFile, Integer> entry : entrySet) { IFile file = entry.getKey(); if(file != null){ CCommandDSC cmd = sid.commandIdCommandMap.get(entry.getValue()); if(cmd != null){ PathInfo fpi = createFilePathInfo(cmd); map.put(file, fpi); } } } if(project != null){ if(psi == null){ generateProjectScannerInfo(); } PathInfo fpi = new PathInfo(psi.includePaths, psi.quoteIncludePaths, psi.definedSymbols, psi.includeFiles, psi.macrosFiles); map.put(project, fpi); } return map; } protected static PathInfo createFilePathInfo(CCommandDSC cmd){ IPath[] includes = stringListToPathArray(cmd.getIncludes()); IPath[] quotedIncludes = stringListToPathArray(cmd.getQuoteIncludes()); IPath[] incFiles = stringListToPathArray(cmd.getIncludeFile()); IPath[] macroFiles = stringListToPathArray(cmd.getImacrosFile()); List<String> symbols = cmd.getSymbols(); Map<String, String> definedSymbols = new HashMap<String, String>(symbols.size()); for (String symbol : symbols) { String key = ScannerConfigUtil.getSymbolKey(symbol); String value = ScannerConfigUtil.getSymbolValue(symbol); definedSymbols.put(key, value); } return new PathInfo(includes, quotedIncludes, definedSymbols, incFiles, macroFiles); } protected CCommandDSC getCommand(IPath path) { try { IFile file = project.getWorkspace().getRoot().getFile(path); return getCommand(file); } catch (Exception e) { return null; } } protected CCommandDSC getCommand(IFile file) { CCommandDSC cmd = null; if (file != null) { Integer cmdId = sid.fileToCommandIdMap.get(file); if (cmdId != null) { // get the command cmd = sid.commandIdCommandMap.get(cmdId); } } return cmd; } /** * @param type can be one of the following: * <li><code>INCLUDE_PATH</code> * <li><code>QUOTE_INCLUDE_PATH</code> * <li><code>INCLUDE_FILE</code> * <li><code>MACROS_FILE</code> * * @return list of IPath(s). */ protected IPath[] getAllIncludePaths(int type) { List<String> allIncludes = new ArrayList<String>(); Set<Integer> cmdIds = sid.commandIdCommandMap.keySet(); for (Integer cmdId : cmdIds) { CCommandDSC cmd = sid.commandIdCommandMap.get(cmdId); if (cmd.isDiscovered()) { List<String> discovered = null; switch (type) { case INCLUDE_PATH: discovered = cmd.getIncludes(); break; case QUOTE_INCLUDE_PATH: discovered = cmd.getQuoteIncludes(); break; case INCLUDE_FILE: discovered = cmd.getIncludeFile(); break; case MACROS_FILE: discovered = cmd.getImacrosFile(); break; default: discovered = new ArrayList<String>(0); } for (String include : discovered) { // the following line degrades perfomance // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=189127 // it is not necessary for renaming projects anyway // include = CCommandDSC.makeRelative(project, new Path(include)).toPortableString(); if (!allIncludes.contains(include)) { allIncludes.add(include); } } } } return stringListToPathArray(allIncludes); } protected static IPath[] stringListToPathArray(List<String> discovered) { List<Path> allIncludes = new ArrayList<Path>(discovered.size()); for (String include : discovered) { if (!allIncludes.contains(include)) { allIncludes.add(new Path(include)); } } return allIncludes.toArray(new IPath[allIncludes.size()]); } protected Map<String, String> getAllSymbols() { assert Thread.holdsLock(fLock); Map<String, String> symbols = new HashMap<String, String>(); Set<Integer> cmdIds = sid.commandIdCommandMap.keySet(); for (Integer cmdId : cmdIds) { CCommandDSC cmd = sid.commandIdCommandMap.get(cmdId); if (cmd.isDiscovered()) { List<String> discovered = cmd.getSymbols(); for (String symbol : discovered) { String key = SafeStringInterner.safeIntern(ScannerConfigUtil.getSymbolKey(symbol)); String value = SafeStringInterner.safeIntern(ScannerConfigUtil.getSymbolValue(symbol)); symbols.put(key, value); } } } return symbols; } }