blob: 5349ec292584d90b32eef95e7bc202b278288edd [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.base.projectview.parser;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.idea.blaze.base.projectview.ProjectView;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.ProjectViewStorageManager;
import com.google.idea.blaze.base.projectview.section.Section;
import com.google.idea.blaze.base.projectview.section.SectionParser;
import com.google.idea.blaze.base.projectview.section.sections.Sections;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/** Parses and writes project views. */
public class ProjectViewParser {
private final BlazeContext context;
private final WorkspacePathResolver workspacePathResolver;
private final boolean recursive;
Set<File> encounteredProjectViewFiles = Sets.newHashSet();
ImmutableList.Builder<ProjectViewSet.ProjectViewFile> projectViewFiles = ImmutableList.builder();
public ProjectViewParser(BlazeContext context, WorkspacePathResolver workspacePathResolver) {
this.context = context;
this.workspacePathResolver = workspacePathResolver;
this.recursive = true;
}
public void parseProjectView(File projectViewFile) {
if (!encounteredProjectViewFiles.add(projectViewFile)) {
return;
}
String projectViewText = null;
try {
projectViewText = ProjectViewStorageManager.getInstance().loadProjectView(projectViewFile);
} catch (IOException e) {
// Error handled below
}
if (projectViewText == null) {
IssueOutput.error(
String.format("Could not load project view file: '%s'", projectViewFile.getPath()))
.submit(context);
return;
}
parseProjectView(
new ParseContext(context, workspacePathResolver, projectViewFile, projectViewText));
}
public void parseProjectView(String text) {
if (text.isEmpty()) {
ProjectView projectView = new ProjectView(ImmutableList.of());
projectViewFiles.add(new ProjectViewSet.ProjectViewFile(projectView, null));
return;
}
parseProjectView(new ParseContext(context, workspacePathResolver, null, text));
}
private void parseProjectView(ParseContext parseContext) {
ImmutableList.Builder<Section<?>> sections = ImmutableList.builder();
List<SectionParser> sectionParsers = Sections.getParsers();
while (!parseContext.atEnd()) {
Section section = null;
for (SectionParser sectionParser : sectionParsers) {
section = sectionParser.parse(this, parseContext);
if (section != null) {
sections.add(section);
break;
}
}
if (section == null) {
if (parseContext.current().indent != 0) {
parseContext.addError(
String.format("Invalid indentation on line: '%s'", parseContext.current().text));
skipSection(parseContext);
} else {
parseContext.addError(
String.format("Could not parse: '%s'", parseContext.current().text));
parseContext.consume();
// Skip past the entire section
skipSection(parseContext);
}
}
}
ProjectView projectView = new ProjectView(sections.build());
projectViewFiles.add(
new ProjectViewSet.ProjectViewFile(projectView, parseContext.getProjectViewFile()));
}
/** Skips all lines until the next unindented, non-empty line. */
private static void skipSection(ParseContext parseContext) {
while (!parseContext.atEnd() && parseContext.current().indent != 0) {
parseContext.consume();
}
}
public boolean isRecursive() {
return recursive;
}
public ProjectViewSet getResult() {
return new ProjectViewSet(projectViewFiles.build());
}
public static String projectViewToString(ProjectView projectView) {
StringBuilder sb = new StringBuilder();
List<SectionParser> sectionParsers = Sections.getParsers();
for (Section<?> section : projectView.getSections()) {
SectionParser sectionParser =
sectionParsers
.stream()
.filter(parser -> section.isSectionType(parser.getSectionKey()))
.findFirst()
.orElse(null);
if (sectionParser != null) {
sectionParser.print(sb, section);
}
}
// Because we split lines we'll always have an extra newline at the end
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}