/******************************************************************************* * Copyright (c) 2016 QNX Software Systems 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 *******************************************************************************/ package org.eclipse.cdt.core.build; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.parser.IExtendedScannerInfo; import org.eclipse.core.resources.IResource; /** * Scanner info for a given build configuration. * * @since 6.1 */ public class ScannerInfoCache { private static class Command { public List<String> command; public IExtendedScannerInfo info; public List<String> resourcePaths; } private List<Command> commands; private transient Map<List<String>, Command> commandMap = new HashMap<>(); private transient Map<String, Command> resourceMap = new HashMap<>(); /** * Initialize the cache of scanner info. Call this after loading this info * using Gson. */ public void initCache() { if (commands == null) { commands = new ArrayList<>(); } for (Command command : commands) { commandMap.put(command.command, command); for (String resourcePath : command.resourcePaths) { resourceMap.put(resourcePath, command); } } } public IExtendedScannerInfo getScannerInfo(IResource resource) { String resourcePath = resource.getLocation().toOSString(); Command command = resourceMap.get(resourcePath); return command != null ? command.info : null; } public IExtendedScannerInfo getScannerInfo(List<String> commandStrings) { Command command = commandMap.get(commandStrings); return command != null ? command.info : null; } public boolean hasCommand(List<String> commandStrings) { return commandMap.get(commandStrings) != null; } public void addScannerInfo(List<String> commandStrings, IExtendedScannerInfo info, IResource resource) { // Do I need to remove the resource from an existing command? String resourcePath = resource.getLocation().toOSString(); Command oldCommand = resourceMap.get(resourcePath); if (oldCommand != null) { if (oldCommand.command.equals(commandStrings)) { // duplicate return; } else { oldCommand.resourcePaths.remove(resourcePath); if (oldCommand.resourcePaths.isEmpty()) { // unused, remove commandMap.remove(commandStrings); commands.remove(oldCommand); resourceMap.remove(resourcePath); } } } Command command = commandMap.get(commandStrings); if (command != null) { command.info = info; command.resourcePaths.add(resourcePath); resourceMap.put(resourcePath, command); } else { command = new Command(); command.command = commandStrings; command.info = info; command.resourcePaths = new ArrayList<>(); command.resourcePaths.add(resourcePath); commands.add(command); commandMap.put(commandStrings, command); resourceMap.put(resourcePath, command); } } public void addResource(List<String> commandStrings, IResource resource) { String resourcePath = resource.getLocation().toOSString(); Command command = commandMap.get(commandStrings); Command current = resourceMap.get(resourcePath); if (current != null) { if (!current.equals(command)) { // remove from old command current.resourcePaths.remove(resourcePath); if (current.resourcePaths.isEmpty()) { commands.remove(current); commandMap.remove(current.command); } } else { // we're already there return; } } command.resourcePaths.add(resource.getLocation().toOSString()); resourceMap.put(resourcePath, command); } }