| /* |
| * 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(); |
| } |
| } |