blob: 562615c1386177954425b9bcbd8ce4e94e8d0b8d [file] [log] [blame]
/*
* Copyright 2016 The Bazel Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.idea.blaze.cpp;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.jetbrains.cidr.lang.autoImport.OCDefaultAutoImportHelper;
import com.jetbrains.cidr.lang.workspace.OCResolveRootAndConfiguration;
import com.jetbrains.cidr.lang.workspace.headerRoots.HeadersSearchRoot;
import com.jetbrains.cidr.lang.workspace.headerRoots.IncludedHeadersRoot;
import java.util.List;
import javax.annotation.Nullable;
/**
* CLion's auto-import suggestions result in include paths relative to the current file (CPP-7593,
* CPP-6369). Instead, we want paths relative to the header search root (e.g. the relevant
* blaze/bazel package path). Presumably this will be fixed in a future CLion release, but in the
* meantime, fix it ourselves.
*/
public class BlazeCppAutoImportHelper extends OCDefaultAutoImportHelper {
@Override
public boolean supports(OCResolveRootAndConfiguration rootAndConfiguration) {
return rootAndConfiguration.getConfiguration() instanceof BlazeResolveConfiguration;
}
/**
* Search in the configuration's header roots only. All other cases are covered by CLion's default
* implementation.
*/
@Override
public boolean processPathSpecificationToInclude(
Project project,
@Nullable VirtualFile targetFile,
VirtualFile fileToImport,
OCResolveRootAndConfiguration rootAndConfiguration,
Processor<ImportSpecification> processor) {
// Check system headers of library roots first. Project roots may include the workspace root,
// and the system headers might be under the workspace root as well.
ImportSpecification specification =
findMatchingRoot(
fileToImport,
rootAndConfiguration.getLibraryHeadersRoots().getRoots(),
/* asUserHeader= */ false);
if (specification != null && !processor.process(specification)) {
return false;
}
specification =
findMatchingRoot(
fileToImport,
rootAndConfiguration.getProjectHeadersRoots().getRoots(),
/* asUserHeader= */ true);
return specification == null || processor.process(specification);
}
@Nullable
private static ImportSpecification findMatchingRoot(
VirtualFile fileToImport, List<HeadersSearchRoot> roots, boolean asUserHeader) {
for (HeadersSearchRoot root : roots) {
if (!(root instanceof IncludedHeadersRoot)) {
continue;
}
IncludedHeadersRoot includedHeadersRoot = (IncludedHeadersRoot) root;
if (asUserHeader != includedHeadersRoot.isUserHeaders()) {
continue;
}
VirtualFile rootBase = root.getVirtualFile();
String relativePath = VfsUtilCore.getRelativePath(fileToImport, rootBase);
if (relativePath == null) {
continue;
}
return new ImportSpecification(
relativePath,
asUserHeader
? ImportSpecification.Kind.USER_HEADER_SEARCH_PATH
: ImportSpecification.Kind.SYSTEM_HEADER_SEARCH_PATH);
}
return null;
}
}