blob: 60ec9caec169d897426bbf4cc79b26c8077a4542 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Mark Schallerf7cb6682015-03-30 14:37:36 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.skyframe;
15
Mark Schallerd7311e02015-07-07 16:36:09 +000016import com.google.common.base.Function;
Mark Schaller66b35f32015-05-19 21:19:37 +000017import com.google.common.collect.ImmutableList;
Mark Schallerd7311e02015-07-07 16:36:09 +000018import com.google.common.collect.Iterables;
Mark Schallerf7cb6682015-03-30 14:37:36 +000019import com.google.devtools.build.lib.cmdline.TargetParsingException;
20import com.google.devtools.build.lib.events.Event;
21import com.google.devtools.build.lib.events.EventHandler;
Mark Schallerf7cb6682015-03-30 14:37:36 +000022import com.google.devtools.build.lib.pkgcache.ParseFailureListener;
Mark Schallerd7311e02015-07-07 16:36:09 +000023import com.google.devtools.build.lib.skyframe.PrepareDepsOfPatternValue.PrepareDepsOfPatternSkyKeyOrException;
Mark Schallerf7cb6682015-03-30 14:37:36 +000024import com.google.devtools.build.lib.skyframe.PrepareDepsOfPatternsValue.TargetPatternSequence;
Mark Schaller248f0442015-05-19 17:59:36 +000025import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey;
Mark Schaller6df81792015-12-10 18:47:47 +000026import com.google.devtools.build.lib.util.Preconditions;
Mark Schallerf7cb6682015-03-30 14:37:36 +000027import com.google.devtools.build.skyframe.SkyFunction;
28import com.google.devtools.build.skyframe.SkyKey;
29import com.google.devtools.build.skyframe.SkyValue;
30import com.google.devtools.build.skyframe.ValueOrException;
31
Mark Schallerf7cb6682015-03-30 14:37:36 +000032import java.util.Map;
33
34import javax.annotation.Nullable;
35
36/**
37 * PrepareDepsOfPatternsFunction ensures the graph loads targets matching the pattern sequence and
38 * their transitive dependencies.
39 */
40public class PrepareDepsOfPatternsFunction implements SkyFunction {
41
Janak Ramakrishnan958ef822016-01-07 16:21:39 +000042 public static ImmutableList<SkyKey> getSkyKeys(SkyKey skyKey, EventHandler eventHandler) {
43 TargetPatternSequence targetPatternSequence = (TargetPatternSequence) skyKey.argument();
44 Iterable<PrepareDepsOfPatternSkyKeyOrException> keysMaybe =
45 PrepareDepsOfPatternValue.keys(targetPatternSequence.getPatterns(),
46 targetPatternSequence.getOffset());
47
48 ImmutableList.Builder<SkyKey> skyKeyBuilder = ImmutableList.builder();
49 boolean handlerIsParseFailureListener = eventHandler instanceof ParseFailureListener;
50 for (PrepareDepsOfPatternSkyKeyOrException skyKeyOrException : keysMaybe) {
51 try {
52 skyKeyBuilder.add(skyKeyOrException.getSkyKey());
53 } catch (TargetParsingException e) {
54 handleTargetParsingException(eventHandler, handlerIsParseFailureListener,
55 skyKeyOrException.getOriginalPattern(), e);
56 }
57 }
58
59 return skyKeyBuilder.build();
60 }
61
62 private static final Function<SkyKey, TargetPatternKey> SKY_TO_TARGET_PATTERN =
63 new Function<SkyKey, TargetPatternKey>() {
64 @Nullable
65 @Override
66 public TargetPatternKey apply(SkyKey skyKey) {
67 return (TargetPatternKey) skyKey.argument();
68 }
69 };
70
71 public static ImmutableList<TargetPatternKey> getTargetPatternKeys(
72 ImmutableList<SkyKey> skyKeys) {
73 return ImmutableList.copyOf(Iterables.transform(skyKeys, SKY_TO_TARGET_PATTERN));
74 }
75
Mark Schallerf7cb6682015-03-30 14:37:36 +000076 /**
77 * Given a {@link SkyKey} that contains a sequence of target patterns, when this function returns
78 * {@link PrepareDepsOfPatternsValue}, then all targets matching that sequence, and those targets'
79 * transitive dependencies, have been loaded.
80 */
81 @Nullable
82 @Override
83 public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
Mark Schaller66b35f32015-05-19 21:19:37 +000084 EventHandler eventHandler = env.getListener();
Janak Ramakrishnan958ef822016-01-07 16:21:39 +000085 ImmutableList<SkyKey> skyKeys = getSkyKeys(skyKey, eventHandler);
Mark Schaller66b35f32015-05-19 21:19:37 +000086
Mark Schallerd7311e02015-07-07 16:36:09 +000087 Map<SkyKey, ValueOrException<TargetParsingException>> tokensByKey =
Mark Schaller66b35f32015-05-19 21:19:37 +000088 env.getValuesOrThrow(skyKeys, TargetParsingException.class);
Mark Schallerf7cb6682015-03-30 14:37:36 +000089 if (env.valuesMissing()) {
90 return null;
91 }
92
Janak Ramakrishnan958ef822016-01-07 16:21:39 +000093 boolean handlerIsParseFailureListener = eventHandler instanceof ParseFailureListener;
Mark Schaller66b35f32015-05-19 21:19:37 +000094 for (SkyKey key : skyKeys) {
Mark Schallerf7cb6682015-03-30 14:37:36 +000095 try {
Mark Schallerd7311e02015-07-07 16:36:09 +000096 // The only exception type throwable by PrepareDepsOfPatternFunction is
97 // TargetParsingException. Therefore all ValueOrException values in the map will either
98 // be non-null or throw TargetParsingException when get is called.
99 Preconditions.checkNotNull(tokensByKey.get(key).get());
Mark Schallerf7cb6682015-03-30 14:37:36 +0000100 } catch (TargetParsingException e) {
101 // If a target pattern can't be evaluated, notify the user of the problem and keep going.
102 handleTargetParsingException(eventHandler, handlerIsParseFailureListener, key, e);
103 }
104 }
Mark Schallerf7cb6682015-03-30 14:37:36 +0000105
Janak Ramakrishnan958ef822016-01-07 16:21:39 +0000106 return new PrepareDepsOfPatternsValue(getTargetPatternKeys(skyKeys));
Mark Schallerf7cb6682015-03-30 14:37:36 +0000107 }
108
109 private static void handleTargetParsingException(EventHandler eventHandler,
110 boolean handlerIsParseFailureListener, SkyKey key, TargetParsingException e) {
Mark Schaller66b35f32015-05-19 21:19:37 +0000111 TargetPatternKey patternKey = (TargetPatternKey) key.argument();
112 String rawPattern = patternKey.getPattern();
113 handleTargetParsingException(eventHandler, handlerIsParseFailureListener, rawPattern, e);
114 }
115
116 private static void handleTargetParsingException(EventHandler eventHandler,
117 boolean handlerIsParseFailureListener, String rawPattern, TargetParsingException e) {
Mark Schallerf7cb6682015-03-30 14:37:36 +0000118 String errorMessage = e.getMessage();
119 eventHandler.handle(Event.error("Skipping '" + rawPattern + "': " + errorMessage));
120 if (handlerIsParseFailureListener) {
121 ParseFailureListener parseListener = (ParseFailureListener) eventHandler;
Mark Schaller66b35f32015-05-19 21:19:37 +0000122 parseListener.parsingError(rawPattern, errorMessage);
Mark Schallerf7cb6682015-03-30 14:37:36 +0000123 }
124 }
125
126 @Nullable
127 @Override
128 public String extractTag(SkyKey skyKey) {
129 return null;
130 }
131
132}