/*******************************************************************************
 * Copyright (c) 2009, 2014 Andrew Gvozdev and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Andrew Gvozdev - initial API and implementation
 *******************************************************************************/

package org.eclipse.cdt.managedbuilder.language.settings.providers;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.EFSExtensionProvider;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
import org.eclipse.cdt.core.language.settings.providers.ICBuildOutputParser;
import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializableProvider;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.LRUCache;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
import org.eclipse.cdt.utils.EFSExtensionManager;
import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.w3c.dom.Element;

/**
 * Abstract class for language settings providers capable to parse build output.
 * <p>
 * <strong>EXPERIMENTAL</strong>. This class interface is not stable yet as
 * it is not currently (CDT 8.1, Juno) clear how it may need to be used in future.
 * There is no guarantee that this API will work or that it will remain the same.
 * Please do not use this API without consulting with the CDT team.
 * </p>
 * @noextend This class is not intended to be subclassed by clients.
 *
 * @since 8.1
 */
public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSettingsSerializableProvider
		implements ICBuildOutputParser {
	protected static final String ATTR_KEEP_RELATIVE_PATHS = "keep-relative-paths"; //$NON-NLS-1$
	// evaluates to "/${ProjName)/"
	private static final String PROJ_NAME_PREFIX = '/'
			+ CdtVariableResolver.createVariableReference(CdtVariableResolver.VAR_PROJ_NAME) + '/';

	protected ICConfigurationDescription currentCfgDescription = null;
	protected IWorkingDirectoryTracker cwdTracker = null;
	protected IProject currentProject = null;
	protected IResource currentResource = null;
	protected String currentLanguageId = null;

	protected String parsedResourceName = null;
	protected boolean isResolvingPaths = true;

	private static final int FIND_RESOURCES_CACHE_SIZE = 100;

	private LRUCache<URI, IResource[]> workspaceRootFindContainersForLocationURICache = new LRUCache<>(
			FIND_RESOURCES_CACHE_SIZE);
	private LRUCache<URI, IResource[]> workspaceRootFindFilesForLocationURICache = new LRUCache<>(
			FIND_RESOURCES_CACHE_SIZE);
	private HashMap<IProject, LRUCache<IPath, List<IResource>>> findPathInProjectCache = new HashMap<>();

	//String pathStr, URI baseURI -> URI
	private static class MappedURIKey {
		URI baseURI;
		String pathStr;

		public MappedURIKey(URI baseURI, String pathStr) {
			super();
			this.baseURI = baseURI;
			this.pathStr = pathStr;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((baseURI == null) ? 0 : baseURI.hashCode());
			result = prime * result + ((pathStr == null) ? 0 : pathStr.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			MappedURIKey other = (MappedURIKey) obj;
			if (baseURI == null) {
				if (other.baseURI != null)
					return false;
			} else if (!baseURI.equals(other.baseURI))
				return false;
			if (pathStr == null) {
				if (other.pathStr != null)
					return false;
			} else if (!pathStr.equals(other.pathStr))
				return false;
			return true;
		}
	}

	// Caches the result of determineMappedURI
	private LRUCache<MappedURIKey, URI> mappedURICache = new LRUCache<>(FIND_RESOURCES_CACHE_SIZE);
	// Caches the result of getFilesystemLocation
	private LRUCache<URI, IPath> fileSystemLocationCache = new LRUCache<>(FIND_RESOURCES_CACHE_SIZE);
	// Caches the result of new File(pathname).exists()
	private LRUCache<IPath, Boolean> pathExistsCache = new LRUCache<>(FIND_RESOURCES_CACHE_SIZE);

	/** @since 8.2 */
	protected EFSExtensionProvider efsProvider = null;

	private static final EFSExtensionProvider efsProviderDefault = new EFSExtensionProvider() {
		final EFSExtensionManager efsManager = EFSExtensionManager.getDefault();

		@Override
		public String getPathFromURI(URI locationURI) {
			return efsManager.getPathFromURI(locationURI);
		}

		@Override
		public URI getLinkedURI(URI locationURI) {
			return efsManager.getLinkedURI(locationURI);
		}

		@Override
		public URI createNewURIFromPath(URI locationOnSameFilesystem, String path) {
			return efsManager.createNewURIFromPath(locationOnSameFilesystem, path);
		}

		@Override
		public String getMappedPath(URI locationURI) {
			return efsManager.getMappedPath(locationURI);
		}

		@Override
		public boolean isVirtual(URI locationURI) {
			return efsManager.isVirtual(locationURI);
		}

		@Override
		public URI append(URI baseURI, String extension) {
			return efsManager.append(baseURI, extension);
		}
	};

	/**
	 * Abstract class defining common functionality for option parsers.
	 * The purpose of this parser is to parse a portion of string representing
	 * a single option and create a language settings entry out of it.
	 *
	 * See {@link GCCBuildCommandParser} for an example how to define the parsers.
	 */
	protected static abstract class AbstractOptionParser {
		private final int kind;
		private final Pattern pattern;
		private final int extraFlag;

		private String parsedName;
		private String parsedValue;
		private final Pattern removeExtraFileNamePattern;

		private static final Pattern numGroupPattern = Pattern.compile("\\$(\\d+)"); //$NON-NLS-1$
		private final MatcherReplacement nameMatcherReplacement;
		private final MatcherReplacement valueMatcherReplacement;

		/**
		 * Constructor.
		 *
		 * @param kind - kind of language settings entries being parsed by the parser.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * 					The pattern may be embedded into another pattern for intermediate
		 * 					parsing so it is best to avoid using numbered group back-reference e.g. \1
		 * @param nameExpression - capturing group expression (numbered or named) defining name of an entry.
		 * @param valueExpression - capturing group expression (numbered or named) defining value of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public AbstractOptionParser(int kind, String pattern, String nameExpression, String valueExpression,
				int extraFlag) {
			this.kind = kind;
			this.extraFlag = extraFlag;

			this.pattern = Pattern.compile(pattern);
			this.removeExtraFileNamePattern = Pattern.compile("(" + pattern + ").*"); //$NON-NLS-1$ //$NON-NLS-2$

			nameMatcherReplacement = new MatcherReplacement(nameExpression);
			valueMatcherReplacement = new MatcherReplacement(valueExpression);
		}

		// Represents a replacement to be applied on a matcher, pre-calculating the group number used in the replacement if possible.
		private static class MatcherReplacement {
			private final String replacementExpression;
			private final int replacementGroupNum;

			private MatcherReplacement(String replacementExpression) {
				this.replacementExpression = replacementExpression;
				int groupNum = -1;
				if (replacementExpression != null) {
					// If the expression is just a single numbered group reference (the common case), we can predetermine
					// which group we will need to retrieve on the matcher when we will parse the option string.
					Matcher numGroupMatcher = numGroupPattern.matcher(replacementExpression);
					if (numGroupMatcher.matches())
						groupNum = Integer.parseInt(numGroupMatcher.group(1));
				}
				replacementGroupNum = groupNum;
			}

			private String replace(Matcher matcher) {
				if (replacementGroupNum != -1)
					return matcher.group(replacementGroupNum);
				// The expression is not a simple numbered group, fall-back to normal replacement (slow).
				if (replacementExpression != null)
					return matcher.replaceAll(replacementExpression);
				return null;
			}
		}

		/**
		 * Create language settings entry of appropriate kind and considering extra-flag passed in constructor.
		 *
		 * @param name - name of language settings entry.
		 * @param value - value of language settings entry.
		 * @param flag - flag to set. Note that the flag will be amended with the extra-flag defined in constructor.
		 * @return new language settings entry.
		 */
		public ICLanguageSettingEntry createEntry(String name, String value, int flag) {
			return (ICLanguageSettingEntry) CDataUtil.createEntry(kind, name, value, null, flag | extraFlag);
		}

		/**
		 * Check if the king of option parsed by parser is "file".
		 *
		 * @return {@code true} if the kind is file, {@code false} otherwise.
		 */
		public boolean isForFile() {
			return kind == ICSettingEntry.INCLUDE_FILE || kind == ICSettingEntry.MACRO_FILE;
		}

		/**
		 * Check if the king of option parsed by parser is "folder".
		 *
		 * @return {@code true} if the kind is folder, {@code false} otherwise.
		 */
		public boolean isForFolder() {
			return kind == ICSettingEntry.INCLUDE_PATH || kind == ICSettingEntry.LIBRARY_PATH;
		}

		/**
		 * Test for a match and parse a portion of input string representing a single option
		 * to retrieve name and value.
		 *
		 * @param optionString - an option to test and parse, possibly with an argument.
		 * @return {@code true} if the option is a match to parser's regular expression
		 *    or {@code false} otherwise.
		 */
		public boolean parseOption(String optionString) {
			// get rid of extra text at the end (for example file name could be confused for an argument)
			Matcher matcherRemoveExtra = removeExtraFileNamePattern.matcher(optionString);
			String option = optionString;
			if (!matcherRemoveExtra.matches()) {
				return false;
			}
			option = matcherRemoveExtra.group(1);

			Matcher matcher = pattern.matcher(option);
			boolean isMatch = matcher.matches();
			if (isMatch) {
				parsedName = nameMatcherReplacement.replace(matcher);
				parsedValue = valueMatcherReplacement.replace(matcher);
			}
			return isMatch;
		}
	}

	/**
	 * Implementation of {@link AbstractOptionParser} for include path options parsing.
	 */
	protected static class IncludePathOptionParser extends AbstractOptionParser {
		public IncludePathOptionParser(String pattern, String nameExpression) {
			super(ICLanguageSettingEntry.INCLUDE_PATH, pattern, nameExpression, nameExpression, 0);
		}

		public IncludePathOptionParser(String pattern, String nameExpression, int extraFlag) {
			super(ICLanguageSettingEntry.INCLUDE_PATH, pattern, nameExpression, nameExpression, extraFlag);
		}
	}

	/**
	 * Implementation of {@link AbstractOptionParser} for include file options parsing.
	 */
	protected static class IncludeFileOptionParser extends AbstractOptionParser {
		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 */
		public IncludeFileOptionParser(String pattern, String nameExpression) {
			super(ICLanguageSettingEntry.INCLUDE_FILE, pattern, nameExpression, nameExpression, 0);
		}

		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public IncludeFileOptionParser(String pattern, String nameExpression, int extraFlag) {
			super(ICLanguageSettingEntry.INCLUDE_FILE, pattern, nameExpression, nameExpression, extraFlag);
		}
	}

	/**
	 * Implementation of {@link AbstractOptionParser} for macro options parsing.
	 */
	protected static class MacroOptionParser extends AbstractOptionParser {
		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param valueExpression - capturing group expression defining value of an entry.
		 */
		public MacroOptionParser(String pattern, String nameExpression, String valueExpression) {
			super(ICLanguageSettingEntry.MACRO, pattern, nameExpression, valueExpression, 0);
		}

		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param valueExpression - capturing group expression defining value of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public MacroOptionParser(String pattern, String nameExpression, String valueExpression, int extraFlag) {
			super(ICLanguageSettingEntry.MACRO, pattern, nameExpression, valueExpression, extraFlag);
		}

		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public MacroOptionParser(String pattern, String nameExpression, int extraFlag) {
			super(ICLanguageSettingEntry.MACRO, pattern, nameExpression, null, extraFlag);
		}
	}

	/**
	 * Implementation of {@link AbstractOptionParser} for macro file options parsing.
	 */
	protected static class MacroFileOptionParser extends AbstractOptionParser {
		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 */
		public MacroFileOptionParser(String pattern, String nameExpression) {
			super(ICLanguageSettingEntry.MACRO_FILE, pattern, nameExpression, nameExpression, 0);
		}

		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public MacroFileOptionParser(String pattern, String nameExpression, int extraFlag) {
			super(ICLanguageSettingEntry.MACRO_FILE, pattern, nameExpression, nameExpression, extraFlag);
		}
	}

	/**
	 * Implementation of {@link AbstractOptionParser} for library path options parsing.
	 */
	protected static class LibraryPathOptionParser extends AbstractOptionParser {
		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 */
		public LibraryPathOptionParser(String pattern, String nameExpression) {
			super(ICLanguageSettingEntry.LIBRARY_PATH, pattern, nameExpression, nameExpression, 0);
		}

		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public LibraryPathOptionParser(String pattern, String nameExpression, int extraFlag) {
			super(ICLanguageSettingEntry.LIBRARY_PATH, pattern, nameExpression, nameExpression, extraFlag);
		}
	}

	/**
	 * Implementation of {@link AbstractOptionParser} for library file options parsing.
	 */
	protected static class LibraryFileOptionParser extends AbstractOptionParser {
		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 */
		public LibraryFileOptionParser(String pattern, String nameExpression) {
			super(ICLanguageSettingEntry.LIBRARY_FILE, pattern, nameExpression, nameExpression, 0);
		}

		/**
		 * Constructor.
		 * @param pattern - regular expression pattern being parsed by the parser.
		 * @param nameExpression - capturing group expression defining name of an entry.
		 * @param extraFlag - extra-flag to add while creating language settings entry.
		 */
		public LibraryFileOptionParser(String pattern, String nameExpression, int extraFlag) {
			super(ICLanguageSettingEntry.LIBRARY_FILE, pattern, nameExpression, nameExpression, extraFlag);
		}
	}

	/**
	 * Parse the line returning the resource name as appears in the output.
	 * This is the resource where {@link ICLanguageSettingEntry} list is being added.
	 *
	 * @param line - one input line from the output stripped from end of line characters.
	 * @return the resource name as appears in the output or {@code null}.
	 *    Note that {@code null} can have different semantics and can mean "no resource found"
	 *    or "applicable to any resource". By default "no resource found" is used in this
	 *    abstract class but extenders can handle otherwise.
	 */
	protected abstract String parseResourceName(String line);

	/**
	 * Parse the line returning the list of substrings to be treated each as input to
	 * the option parsers. It is assumed that each substring presents one
	 * {@link ICLanguageSettingEntry} (for example compiler options {@code -I/path} or
	 * {@code -DMACRO=1}).
	 *
	 * @param line - one input line from the output stripped from end of line characters.
	 * @return list of substrings representing language settings entries.
	 */
	protected abstract List<String> parseOptions(String line);

	/**
	 * @return array of option parsers defining how to parse a string to
	 * {@link ICLanguageSettingEntry}.
	 * See {@link AbstractOptionParser} and its specific extenders.
	 */
	protected abstract AbstractOptionParser[] getOptionParsers();

	/**
	 * @return array of option parsers defining how to parse a string to
	 * {@link ICLanguageSettingEntry}.
	 * See {@link AbstractOptionParser} and its specific extenders.
	 *
	 * @param optionToParse the option string to be parsed.
	 * This can be used as a hint in order to return a subset of parsers, for better performance.
	 *
	 * @since 9.1
	 */
	protected AbstractOptionParser[] getOptionParsers(String optionToParse) {
		return getOptionParsers();
	}

	/**
	 * @return {@code true} when the provider tries to resolve relative or remote paths
	 * to the existing paths in the workspace or local file-system using certain heuristics.
	 */
	public boolean isResolvingPaths() {
		return isResolvingPaths;
	}

	/**
	 * Enable or disable resolving  relative or remote paths to the existing paths
	 * in the workspace or local file-system.
	 *
	 * @param resolvePaths - set {@code true} to enable or {@code false} to disable
	 *    resolving paths. When this parameter is set to {@code false} the paths will
	 *    be kept as they appear in the build output.
	 */
	public void setResolvingPaths(boolean resolvePaths) {
		this.isResolvingPaths = resolvePaths;
	}

	@Override
	public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker)
			throws CoreException {
		this.currentCfgDescription = cfgDescription;
		this.currentProject = cfgDescription != null ? cfgDescription.getProjectDescription().getProject() : null;
		this.cwdTracker = cwdTracker;
		this.efsProvider = getEFSProvider();
	}

	@Override
	public void shutdown() {
		// release resources for garbage collector
		// but keep currentCfgDescription for AbstractBuiltinSpecsDetector flow
		parsedResourceName = null;
		currentLanguageId = null;
		currentResource = null;
		cwdTracker = null;
		clearCaches();
	}

	private void clearCaches() {
		workspaceRootFindContainersForLocationURICache.clear();
		workspaceRootFindFilesForLocationURICache.clear();
		findPathInProjectCache.clear();
		mappedURICache.clear();
		fileSystemLocationCache.clear();
		pathExistsCache.clear();
	}

	@Override
	public boolean processLine(String line) {
		parsedResourceName = parseResourceName(line);
		currentResource = findResource(parsedResourceName);

		currentLanguageId = determineLanguage();
		if (!isLanguageInScope(currentLanguageId)) {
			return false;
		}

		/**
		 * URI of directory where the build is happening. This URI could point to a remote file-system
		 * for remote builds. Most often it is the same file-system as for currentResource but
		 * it can be different file-system (and different URI schema).
		 */
		URI buildDirURI = null;

		/**
		 * Where source tree starts if mapped. This kind of mapping is useful for example in cases when
		 * the absolute path to the source file on the remote system is simulated inside a project in the
		 * workspace.
		 * This URI is rooted on the same file-system where currentResource resides. In general this file-system
		 * (or even URI schema) does not have to match that of buildDirURI.
		 */
		URI mappedRootURI = null;

		if (isResolvingPaths) {
			mappedRootURI = getMappedRootURI(currentResource, parsedResourceName);
			buildDirURI = getBuildDirURI(mappedRootURI);
		}

		List<ICLanguageSettingEntry> entries = new ArrayList<>();

		List<String> options = parseOptions(line);
		if (options != null) {
			for (String option : options) {
				AbstractOptionParser[] optionParsers = getOptionParsers(option);
				for (AbstractOptionParser optionParser : optionParsers) {
					try {
						if (optionParser.parseOption(option)) {
							ICLanguageSettingEntry entry = null;
							if (isResolvingPaths && (optionParser.isForFile() || optionParser.isForFolder())) {
								URI baseURI = mappedRootURI;
								if (buildDirURI != null && !new Path(optionParser.parsedName).isAbsolute()) {
									if (mappedRootURI != null) {
										baseURI = efsProvider.append(mappedRootURI, buildDirURI.getPath());
									} else {
										baseURI = buildDirURI;
									}
								}
								entry = createResolvedPathEntry(optionParser, optionParser.parsedName, 0, baseURI);
							} else {
								entry = optionParser.createEntry(optionParser.parsedName, optionParser.parsedValue, 0);
							}

							if (entry != null && !entries.contains(entry)) {
								entries.add(entry);
								break;
							}
						}
					} catch (Throwable e) {
						@SuppressWarnings("nls")
						String msg = "Exception trying to parse option [" + option + "], class "
								+ getClass().getSimpleName();
						ManagedBuilderCorePlugin
								.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, msg, e));
					}
				}
			}
			if (entries.size() > 0) {
				setSettingEntries(entries);
			} else {
				setSettingEntries(null);
			}
		}
		return false;
	}

	/**
	 * In case when absolute path is mapped to the source tree in a project
	 * this function will try to figure mapping and return "mapped root",
	 * i.e URI where the root path would be mapped. The mapped root will be
	 * used to prepend to other "absolute" paths where appropriate.
	 *
	 * @param resource - a resource referred by parsed path
	 * @param parsedResourceName - path as appears in the output
	 * @return mapped path as URI
	 */
	protected URI getMappedRootURI(IResource resource, String parsedResourceName) {
		if (resource == null) {
			return null;
		}

		URI resourceURI = resource.getLocationURI();
		String mappedRoot = "/"; //$NON-NLS-1$

		if (parsedResourceName != null) {
			IPath parsedSrcPath = new Path(parsedResourceName);
			if (parsedSrcPath.isAbsolute()) {
				IPath absResourcePath = resource.getLocation();
				int absSegmentsCount = absResourcePath.segmentCount();
				int relSegmentsCount = parsedSrcPath.segmentCount();
				if (absSegmentsCount >= relSegmentsCount) {
					IPath ending = absResourcePath.removeFirstSegments(absSegmentsCount - relSegmentsCount);
					ending = ending.setDevice(parsedSrcPath.getDevice()).makeAbsolute();
					if (ending.equals(parsedSrcPath.makeAbsolute())) {
						// mappedRoot here is parsedSrcPath with removed parsedResourceName trailing segments,
						// i.e. if absResourcePath="/path/workspace/project/file.c" and parsedResourceName="project/file.c"
						// then mappedRoot="/path/workspace/"
						mappedRoot = absResourcePath.removeLastSegments(relSegmentsCount).toString();
					}
				}
			}
		}
		// this creates URI with schema and other components from resourceURI but path as mappedRoot
		URI uri = efsProvider.createNewURIFromPath(resourceURI, mappedRoot);
		return uri;
	}

	/**
	 * Determine current build directory considering currentResource (resource being compiled),
	 * parsedResourceName and mappedRootURI.
	 *
	 * @param mappedRootURI - root of the source tree when mapped to remote file-system.
	 * @return {@link URI} of current build directory
	 */
	protected URI getBuildDirURI(URI mappedRootURI) {
		URI buildDirURI = null;

		// try to deduce build directory from full path of currentResource and partial path of parsedResourceName
		URI cwdURI = null;
		if (currentResource != null && parsedResourceName != null && !new Path(parsedResourceName).isAbsolute()) {
			cwdURI = findBaseLocationURI(currentResource.getLocationURI(), parsedResourceName);
		}
		String cwdPath = cwdURI != null ? efsProvider.getPathFromURI(cwdURI) : null;
		if (cwdPath != null && mappedRootURI != null) {
			buildDirURI = efsProvider.append(mappedRootURI, cwdPath);
		} else {
			buildDirURI = cwdURI;
		}

		// try IWorkingDirectoryTracker
		if (buildDirURI == null && cwdTracker != null) {
			buildDirURI = cwdTracker.getWorkingDirectoryURI();
		}

		// try builder working directory
		if (buildDirURI == null && currentCfgDescription != null) {
			IPath pathBuilderCWD = currentCfgDescription.getBuildSetting().getBuilderCWD();
			if (pathBuilderCWD != null) {
				String builderCWD = pathBuilderCWD.toString();
				try {
					// here is a hack to overcome ${workspace_loc:/prj-name} returned by builder
					// where "/" is treated as path separator by pathBuilderCWD
					ICdtVariableManager vmanager = CCorePlugin.getDefault().getCdtVariableManager();
					builderCWD = vmanager.resolveValue(builderCWD, "", null, currentCfgDescription); //$NON-NLS-1$
				} catch (CdtVariableException e) {
					ManagedBuilderCorePlugin.log(e);
				}
				if (builderCWD != null && !builderCWD.isEmpty()) {
					buildDirURI = org.eclipse.core.filesystem.URIUtil.toURI(builderCWD);
				}
			}
		}

		// try directory of the current project
		if (buildDirURI == null && currentProject != null) {
			buildDirURI = currentProject.getLocationURI();
		}

		// try parent folder of the resource
		if (buildDirURI == null && currentResource != null) {
			IContainer container;
			if (currentResource instanceof IContainer) {
				container = (IContainer) currentResource;
			} else {
				container = currentResource.getParent();
			}
			buildDirURI = container.getLocationURI();
		}
		return buildDirURI;
	}

	/**
	 * Sets language settings entries for current configuration description, current resource
	 * and current language ID.
	 *
	 * @param entries - language settings entries to set.
	 */
	protected void setSettingEntries(List<? extends ICLanguageSettingEntry> entries) {
		setSettingEntries(currentCfgDescription, currentResource, currentLanguageId, entries);
	}

	/**
	 * Determine a language associated with the resource.
	 *
	 * @return language ID for the resource.
	 */
	protected String determineLanguage() {
		IResource rc = currentResource;
		if (rc == null && currentProject != null && parsedResourceName != null) {
			String fileName = new Path(parsedResourceName).lastSegment().toString();
			// use handle; resource does not need to exist
			rc = currentProject.getFile("__" + fileName); //$NON-NLS-1$
		}

		if (rc == null)
			return null;

		List<String> languageIds = LanguageSettingsManager.getLanguages(rc, currentCfgDescription);
		if (languageIds.isEmpty())
			return null;

		return languageIds.get(0);
	}

	/**
	 * Determine if the language is in scope of the provider.
	 *
	 * @param languageId - language ID.
	 * @return {@code true} if the language is in scope, {@code false } otherwise.
	 */
	protected boolean isLanguageInScope(String languageId) {
		List<String> languageIds = getLanguageScope();
		return languageIds == null || languageIds.contains(languageId);
	}

	/**
	 * Find file resource in the workspace for a given URI with a preference for the resource
	 * to reside in the given project.
	 */
	private IResource findFileForLocationURI(URI uri, IProject preferredProject, boolean checkExistence) {
		if (!uri.isAbsolute()) {
			// IWorkspaceRoot.findFilesForLocationURI(URI) below requires an absolute URI
			// therefore we haven't/aren't going to find the file based on this URI.
			return null;
		}
		IResource sourceFile = null;

		IResource[] resources = workspaceRootFindFilesForLocationURICache.computeIfAbsent(uri,
				key -> ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(key));
		for (IResource rc : resources) {
			if (!checkExistence || rc.isAccessible()) {
				if (rc.getProject().equals(preferredProject)) {
					sourceFile = rc;
					break;
				}
				if (sourceFile == null) {
					sourceFile = rc;
				}
			}
		}
		return sourceFile;
	}

	/**
	 * Return a resource in workspace corresponding the given folder {@link URI} preferable residing in
	 * the provided project.
	 */
	private IResource findContainerForLocationURI(URI uri, IProject preferredProject, boolean checkExistence) {
		IResource resource = null;

		IResource[] resources = workspaceRootFindContainersForLocationURICache.computeIfAbsent(uri,
				key -> ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(key));
		for (IResource rc : resources) {
			if ((rc instanceof IProject || rc instanceof IFolder) && (!checkExistence || rc.isAccessible())) { // treat IWorkspaceRoot as non-workspace path
				if (rc.getProject().equals(preferredProject)) {
					resource = rc;
					break;
				}
				if (resource == null) {
					resource = rc; // to be deterministic the first qualified resource has preference
				}
			}
		}
		return resource;
	}

	/**
	 * Determine resource in the workspace corresponding to the parsed resource name.
	 */
	private IResource findResource(String parsedResourceName) {
		if (parsedResourceName == null || parsedResourceName.isEmpty()) {
			return null;
		}

		IResource sourceFile = null;

		// try ErrorParserManager
		if (cwdTracker instanceof ErrorParserManager) {
			sourceFile = ((ErrorParserManager) cwdTracker).findFileName(parsedResourceName);
		}

		// try to find absolute path in the workspace
		Path parsedPath = new Path(parsedResourceName);
		if (sourceFile == null && parsedPath.isAbsolute()) {
			// It will often happen that the file will be under the project and in the local file system, so check there first.
			IPath projectLocation = currentProject != null ? currentProject.getLocation() : null;
			if (projectLocation != null) {
				IPath relativePath = parsedPath.makeRelativeTo(projectLocation);
				if (!relativePath.equals(parsedPath)) {
					IFile file = currentProject.getFile(relativePath);
					if (file.isAccessible()) {
						return file;
					}
				}
			}

			URI uri = org.eclipse.core.filesystem.URIUtil.toURI(parsedResourceName);
			sourceFile = findFileForLocationURI(uri, currentProject, /*checkExistence*/ true);
		}

		// try last known current working directory from build output
		if (sourceFile == null && cwdTracker != null) {
			URI cwdURI = cwdTracker.getWorkingDirectoryURI();
			if (cwdURI != null) {
				URI uri = efsProvider.append(cwdURI, parsedResourceName);
				sourceFile = findFileForLocationURI(uri, currentProject, /*checkExistence*/ true);
			}
		}

		// try path relative to build dir from configuration
		if (sourceFile == null && currentCfgDescription != null) {
			IPath builderCWD = currentCfgDescription.getBuildSetting().getBuilderCWD();
			if (builderCWD != null) {
				String strBuilderCWD = builderCWD.toString();
				try {
					ICdtVariableManager varManager = CCorePlugin.getDefault().getCdtVariableManager();
					strBuilderCWD = varManager.resolveValue(strBuilderCWD, "", null, currentCfgDescription); //$NON-NLS-1$
				} catch (Exception e) {
					@SuppressWarnings("nls")
					String msg = "Exception trying to resolve value [" + strBuilderCWD + "]";
					ManagedBuilderCorePlugin.log(new Status(IStatus.ERROR, ManagedBuilderCorePlugin.PLUGIN_ID, msg, e));
				}
				builderCWD = new Path(strBuilderCWD);

				IPath path = builderCWD.append(parsedResourceName);
				URI uri = org.eclipse.core.filesystem.URIUtil.toURI(path);
				sourceFile = findFileForLocationURI(uri, currentProject, /*checkExistence*/ true);
			}
		}

		// try path relative to the project
		if (sourceFile == null && currentProject != null) {
			sourceFile = currentProject.findMember(parsedResourceName);
		}

		return sourceFile;
	}

	/**
	 * Find base location of the file, i.e. location of the directory which
	 * results from removing trailing relativeFileName from fileURI or
	 * {@code null} if fileURI doesn't represent relativeFileName.
	 */
	private static URI findBaseLocationURI(URI fileURI, String relativeFileName) {
		URI cwdURI = null;
		String path = fileURI.getPath();

		String[] segments = relativeFileName.split("[/\\\\]"); //$NON-NLS-1$

		// start removing segments from the end of the path
		for (int i = segments.length - 1; i >= 0; i--) {
			String lastSegment = segments[i];
			if (lastSegment.length() > 0 && !lastSegment.equals(".")) { //$NON-NLS-1$
				if (lastSegment.equals("..")) { //$NON-NLS-1$
					// navigating ".." in the other direction is ambiguous, bailing out
					return null;
				} else {
					if (path.endsWith("/" + lastSegment)) { //$NON-NLS-1$
						int pos = path.lastIndexOf("/" + lastSegment); //$NON-NLS-1$
						path = path.substring(0, pos);
						continue;
					} else {
						// ouch, relativeFileName does not match fileURI, bailing out
						return null;
					}
				}
			}
		}

		try {
			cwdURI = new URI(fileURI.getScheme(), fileURI.getUserInfo(), fileURI.getHost(), fileURI.getPort(),
					path + '/', fileURI.getQuery(), fileURI.getFragment());
		} catch (URISyntaxException e) {
			// It should be valid URI here or something is really wrong
			ManagedBuilderCorePlugin.log(e);
		}

		return cwdURI;
	}

	/**
	 * The manipulations here are done to resolve problems such as "../" navigation for symbolic links where
	 * "link/.." cannot be collapsed as it must follow the real file-system path. {@link java.io.File#getCanonicalPath()}
	 * deals with that correctly but {@link Path} or {@link URI} try to normalize the path which would be incorrect here.
	 * Another issue being resolved here is fixing drive letters in URI syntax.
	 */
	private static URI resolvePathFromBaseLocation(String pathStr0, IPath baseLocation) {
		String pathStr = pathStr0;
		if (baseLocation != null && !baseLocation.isEmpty()) {
			pathStr = pathStr.replace(File.separatorChar, '/');
			String device = new Path(pathStr).getDevice();
			if (device == null || device.equals(baseLocation.getDevice())) {
				if (device != null && device.length() > 0) {
					pathStr = pathStr.substring(device.length());
				}

				baseLocation = baseLocation.addTrailingSeparator();
				if (pathStr.startsWith("/")) { //$NON-NLS-1$
					pathStr = pathStr.substring(1);
				}
				pathStr = baseLocation.toString() + pathStr;
			}
		}

		try {
			File file = new File(pathStr);
			file = file.getCanonicalFile();
			URI uri = file.toURI();
			if (file.exists()) {
				return uri;
			}

			IPath path0 = new Path(pathStr0);
			if (!path0.isAbsolute()) {
				return uri;
			}

			String device = path0.getDevice();
			if (device == null || device.isEmpty()) {
				// Avoid spurious adding of drive letters on Windows
				pathStr = path0.setDevice(null).toString();
			} else {
				// On Windows "C:/folder/" -> "/C:/folder/"
				if (pathStr.charAt(0) != IPath.SEPARATOR) {
					pathStr = IPath.SEPARATOR + pathStr;
				}
			}

			return new URI(uri.getScheme(), uri.getAuthority(), pathStr, uri.getQuery(), uri.getFragment());

		} catch (Exception e) {
			// if error will leave it as is
			ManagedBuilderCorePlugin.log(e);
		}

		return org.eclipse.core.filesystem.URIUtil.toURI(pathStr);
	}

	/**
	 * Determine URI on the local file-system considering possible mapping.
	 *
	 * @param pathStr - path to the resource, can be absolute or relative
	 * @param baseURI - base {@link URI} where path to the resource is rooted
	 * @return {@link URI} of the resource
	 */
	private URI determineMappedURI(String pathStr, URI baseURI) {
		return mappedURICache.computeIfAbsent(new MappedURIKey(baseURI, pathStr), key -> {
			URI uri = null;

			if (baseURI == null) {
				if (new Path(pathStr).isAbsolute()) {
					uri = resolvePathFromBaseLocation(pathStr, Path.ROOT);
				}
			} else if (baseURI.getScheme().equals(EFS.SCHEME_FILE)) {
				// location on the local file-system
				IPath baseLocation = org.eclipse.core.filesystem.URIUtil.toPath(baseURI);
				// careful not to use Path here but 'pathStr' as String as we want to properly navigate symlinks
				uri = resolvePathFromBaseLocation(pathStr, baseLocation);
			} else {
				// location on a remote file-system
				IPath path = new Path(pathStr); // use canonicalized path here, in particular replace all '\' with '/' for Windows paths
				URI remoteUri = efsProvider.append(baseURI, path.toString());
				if (remoteUri != null) {
					String localPath = efsProvider.getMappedPath(remoteUri);
					if (localPath != null) {
						uri = org.eclipse.core.filesystem.URIUtil.toURI(localPath);
					}
				}
			}

			if (uri == null) {
				// if everything fails just wrap string to URI
				uri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr);
			}
			return uri;
		});
	}

	/**
	 * Find all resources in the project which might be represented by relative path passed.
	 */
	private List<IResource> findPathInProject(IPath path, IProject project) {
		LRUCache<IPath, List<IResource>> cache = findPathInProjectCache.computeIfAbsent(project,
				key -> new LRUCache<>(FIND_RESOURCES_CACHE_SIZE));
		return cache.computeIfAbsent(path, key -> findPathInFolder(path, project));
	}

	/**
	 * Find all resources in the folder which might be represented by relative path passed.
	 */
	private static List<IResource> findPathInFolder(IPath path, IContainer folder) {
		List<IResource> paths = new ArrayList<>();
		IResource resource = folder.findMember(path);
		if (resource != null) {
			paths.add(resource);
		}

		try {
			for (IResource res : folder.members()) {
				if (res instanceof IContainer) {
					paths.addAll(findPathInFolder(path, (IContainer) res));
				}
			}
		} catch (CoreException e) {
			// ignore
		}

		return paths;
	}

	/**
	 * Determine which resource in workspace is the best fit to parsedName passed.
	 */
	private IResource findBestFitInWorkspace(String parsedName) {
		Set<String> referencedProjectsNames = new LinkedHashSet<>();
		if (currentCfgDescription != null) {
			Map<String, String> refs = currentCfgDescription.getReferenceInfo();
			referencedProjectsNames.addAll(refs.keySet());
		}

		IPath path = new Path(parsedName);
		if (path.equals(new Path(".")) || path.equals(new Path(".."))) { //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		}

		// prefer current project
		if (currentProject != null) {
			List<IResource> result = findPathInProject(path, currentProject);
			int size = result.size();
			if (size == 1) { // found the one
				return result.get(0);
			} else if (size > 1) { // ambiguous
				return null;
			}
		}

		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

		// then prefer referenced projects
		if (referencedProjectsNames.size() > 0) {
			IResource rc = null;
			for (String prjName : referencedProjectsNames) {
				IProject prj = root.getProject(prjName);
				if (prj.isOpen()) {
					List<IResource> result = findPathInProject(path, prj);
					int size = result.size();
					if (size == 1 && rc == null) {
						rc = result.get(0);
					} else if (size > 0) {
						// ambiguous
						rc = null;
						break;
					}
				}
			}
			if (rc != null) {
				return rc;
			}
		}

		// then check all other projects in workspace
		IProject[] projects = root.getProjects();
		if (projects.length > 0) {
			IResource rc = null;
			for (IProject prj : projects) {
				if (!prj.equals(currentProject) && !referencedProjectsNames.contains(prj.getName()) && prj.isOpen()) {
					List<IResource> result = findPathInProject(path, prj);
					int size = result.size();
					if (size == 1 && rc == null) {
						rc = result.get(0);
					} else if (size > 0) {
						// ambiguous
						rc = null;
						break;
					}
				}
			}
			if (rc != null) {
				return rc;
			}
		}

		// not found or ambiguous
		return null;
	}

	/**
	 * Get location on the local file-system considering possible mapping by EFS provider. See {@link EFSExtensionManager}.
	 */
	private IPath getFilesystemLocation(URI uri) {
		if (uri == null)
			return null;

		return fileSystemLocationCache.computeIfAbsent(uri, (k) -> {
			String pathStr = efsProvider.getMappedPath(uri);
			URI resUri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr);

			if (resUri != null && resUri.isAbsolute()) {
				try {
					File file = new java.io.File(resUri);
					String canonicalPathStr = file.getCanonicalPath();
					if (new Path(pathStr).getDevice() == null) {
						return new Path(canonicalPathStr).setDevice(null);
					}
					return new Path(canonicalPathStr);
				} catch (Exception e) {
					ManagedBuilderCorePlugin.log(e);
				}
			}
			return null;
		});
	}

	/**
	 * Resolve and create language settings path entry.
	 */
	private ICLanguageSettingEntry createResolvedPathEntry(AbstractOptionParser optionParser, String parsedPath,
			int flag, URI baseURI) {
		URI uri = determineMappedURI(parsedPath, baseURI);
		boolean isRelative = !new Path(parsedPath).isAbsolute();
		// is mapped something that is not a project root
		boolean isRemapped = baseURI != null && currentProject != null
				&& !baseURI.equals(currentProject.getLocationURI());
		boolean presentAsRelative = isRelative || isRemapped;

		ICLanguageSettingEntry entry = resolvePathEntryInWorkspace(optionParser, uri, flag, presentAsRelative);
		if (entry != null) {
			return entry;
		}
		entry = resolvePathEntryInFilesystem(optionParser, uri, flag);
		if (entry != null) {
			return entry;
		}
		entry = resolvePathEntryInWorkspaceAsBestFit(optionParser, parsedPath, flag, presentAsRelative);
		if (entry != null) {
			return entry;
		}
		entry = resolvePathEntryInWorkspaceToNonexistingResource(optionParser, uri, flag, presentAsRelative);
		if (entry != null) {
			return entry;
		}
		entry = resolvePathEntryInFilesystemToNonExistingResource(optionParser, uri, flag);
		if (entry != null) {
			return entry;
		}
		return optionParser.createEntry(parsedPath, parsedPath, flag);
	}

	/**
	 * Create a language settings entry for a given resource.
	 * This will represent relative path using CDT variable ${ProjName}.
	 */
	private ICLanguageSettingEntry createPathEntry(AbstractOptionParser optionParser, IResource rc, boolean isRelative,
			int flag) {
		String path;
		if (isRelative && rc.getProject().equals(currentProject)) {
			path = PROJ_NAME_PREFIX + rc.getFullPath().removeFirstSegments(1);
			flag = flag | ICSettingEntry.VALUE_WORKSPACE_PATH;
		} else {
			path = rc.getFullPath().toString();
			flag = flag | ICSettingEntry.VALUE_WORKSPACE_PATH | ICSettingEntry.RESOLVED;
		}
		return optionParser.createEntry(path, path, flag);
	}

	/**
	 * Find an existing resource in the workspace and create a language settings entry for it.
	 */
	private ICLanguageSettingEntry resolvePathEntryInWorkspace(AbstractOptionParser optionParser, URI uri, int flag,
			boolean isRelative) {
		if (uri != null && uri.isAbsolute()) {
			IResource rc = null;
			if (optionParser.isForFolder()) {
				rc = findContainerForLocationURI(uri, currentProject, /*checkExistence*/ true);
			} else if (optionParser.isForFile()) {
				rc = findFileForLocationURI(uri, currentProject, /*checkExistence*/ true);
			}
			if (rc != null) {
				return createPathEntry(optionParser, rc, isRelative, flag);
			}
		}
		return null;
	}

	/**
	 * Find a resource on the file-system and create a language settings entry for it.
	 */
	private ICLanguageSettingEntry resolvePathEntryInFilesystem(AbstractOptionParser optionParser, URI uri, int flag) {
		IPath location = getFilesystemLocation(uri);
		if (location != null) {
			String loc = location.toString();
			boolean exists = pathExistsCache.computeIfAbsent(location, (s) -> {
				return new File(loc).exists();
			});
			if (exists) {
				return optionParser.createEntry(loc, loc, flag);
			}
		}
		return null;
	}

	/**
	 * Find a best fit for the resource in the workspace and create a language settings entry for it.
	 */
	private ICLanguageSettingEntry resolvePathEntryInWorkspaceAsBestFit(AbstractOptionParser optionParser,
			String parsedPath, int flag, boolean isRelative) {
		IResource rc = findBestFitInWorkspace(parsedPath);
		if (rc != null) {
			return createPathEntry(optionParser, rc, isRelative, flag);
		}
		return null;
	}

	/**
	 * Try to map a resource in the workspace even if it does not exist and create a language settings entry for it.
	 */
	private ICLanguageSettingEntry resolvePathEntryInWorkspaceToNonexistingResource(AbstractOptionParser optionParser,
			URI uri, int flag, boolean isRelative) {
		if (uri != null && uri.isAbsolute()) {
			IResource rc = null;
			if (optionParser.isForFolder()) {
				rc = findContainerForLocationURI(uri, currentProject, /*checkExistence*/ false);
			} else if (optionParser.isForFile()) {
				rc = findFileForLocationURI(uri, currentProject, /*checkExistence*/ false);
			}
			if (rc != null) {
				return createPathEntry(optionParser, rc, isRelative, flag);
			}
		}
		return null;
	}

	/**
	 * Try to map a resource on the file-system even if it does not exist and create a language settings entry for it.
	 */
	private ICLanguageSettingEntry resolvePathEntryInFilesystemToNonExistingResource(AbstractOptionParser optionParser,
			URI uri, int flag) {
		IPath location = getFilesystemLocation(uri);
		if (location != null) {
			return optionParser.createEntry(location.toString(), location.toString(), flag);
		}
		return null;
	}

	/**
	 * Count how many groups are present in regular expression.
	 * The implementation is simplistic but should be sufficient for the cause.
	 *
	 * @param str - regular expression to count the groups.
	 * @return number of the groups (groups are enclosed in round brackets) present.
	 */
	protected static int countGroups(String str) {
		@SuppressWarnings("nls")
		int count = str.replaceAll("[^\\(]", "").length();
		return count;
	}

	/**
	 * Helper method to construct logical "or" to be used inside regular expressions.
	 */
	@SuppressWarnings("nls")
	private static String expressionLogicalOr(Set<String> fileExts) {
		String pattern = "(";
		for (String ext : fileExts) {
			if (pattern.length() != 1)
				pattern += "|";
			pattern += "(" + Pattern.quote(ext) + ")";
			ext = ext.toUpperCase();
			if (!fileExts.contains(ext)) {
				pattern += "|(" + Pattern.quote(ext) + ")";
			}
		}
		pattern += ")";
		return pattern;
	}

	/**
	 * Construct regular expression to find any file extension for C or C++.
	 * Returns expression shaped in form of "((cpp)|(c++)|(c))".
	 *
	 * @return regular expression for searching C/C++ file extensions.
	 */
	protected String getPatternFileExtensions() {
		IContentTypeManager manager = Platform.getContentTypeManager();

		Set<String> fileExts = new HashSet<>();

		IContentType contentTypeCpp = manager.getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE);
		fileExts.addAll(Arrays.asList(contentTypeCpp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)));

		IContentType contentTypeC = manager.getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE);
		fileExts.addAll(Arrays.asList(contentTypeC.getFileSpecs(IContentType.FILE_EXTENSION_SPEC)));

		String pattern = expressionLogicalOr(fileExts);

		return pattern;
	}

	/**
	 * This {@link EFSExtensionProvider} is capable to translate EFS paths to and from local
	 * file-system. Added mostly for Cygwin translations.
	 *
	 * This usage of {@link EFSExtensionProvider} is somewhat a misnomer. This provider is not
	 * an "extension" provider but rather a wrapper on {@link EFSExtensionManager} which in fact
	 * will use genuine {@link EFSExtensionProvider}s defined as extensions.
	 *
	 * @since 8.2
	 */
	protected EFSExtensionProvider getEFSProvider() {
		return efsProviderDefault;
	}

	@Override
	public Element serializeAttributes(Element parentElement) {
		Element elementProvider = super.serializeAttributes(parentElement);
		elementProvider.setAttribute(ATTR_KEEP_RELATIVE_PATHS, Boolean.toString(!isResolvingPaths));
		return elementProvider;
	}

	@Override
	public void loadAttributes(Element providerNode) {
		super.loadAttributes(providerNode);

		String expandRelativePathsValue = XmlUtil.determineAttributeValue(providerNode, ATTR_KEEP_RELATIVE_PATHS);
		if (expandRelativePathsValue != null)
			isResolvingPaths = !Boolean.parseBoolean(expandRelativePathsValue);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + (isResolvingPaths ? 1231 : 1237);
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractLanguageSettingsOutputScanner other = (AbstractLanguageSettingsOutputScanner) obj;
		if (isResolvingPaths != other.isResolvingPaths)
			return false;
		return true;
	}

}
